cluaupp 1.5.0 → 1.5.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 (323) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +10 -5
  3. package/api/CHANGELOG.md +3 -0
  4. package/api/chat.js +74 -0
  5. package/api/fixtures/roblox/README.md +6 -0
  6. package/api/fixtures/roblox/aux/sample.d.luau +6 -0
  7. package/api/fixtures/roblox/mini/Mini-API-Dump.json +72 -0
  8. package/api/generated/bench-latest.json +39 -0
  9. package/api/generated/capability-profile.json +76 -0
  10. package/api/generated/lsp-index.json +1 -0
  11. package/api/generated/luau/classes.d.luau +11221 -0
  12. package/api/generated/luau/datatypes.d.luau +327 -0
  13. package/api/generated/luau/enums.d.luau +4918 -0
  14. package/api/generated/luau/globals.d.luau +12 -0
  15. package/api/manifests/roblox-target.manifest.json +22 -0
  16. package/api/normalized/roblox-target.profile.json +237461 -0
  17. package/api/overrides/classes.json +8 -0
  18. package/api/overrides/compatibility.json +9 -0
  19. package/api/overrides/datatypes.json +1579 -0
  20. package/api/overrides/enums.json +8 -0
  21. package/api/overrides/globals.json +8 -0
  22. package/api/overrides/type-mappings.json +9 -0
  23. package/api/roblox-api.lock.json +9 -0
  24. package/data/Mini-API-Dump.json +1 -0
  25. package/editors/vscode/README.md +12 -10
  26. package/editors/vscode/extension.js +82 -0
  27. package/editors/vscode/icons/axiom.svg +4 -0
  28. package/editors/vscode/icons/bloom.svg +5 -0
  29. package/editors/vscode/icons/helm.svg +4 -0
  30. package/editors/vscode/icons/hive.svg +5 -0
  31. package/editors/vscode/icons/mint.svg +4 -0
  32. package/editors/vscode/icons/shift.svg +6 -0
  33. package/editors/vscode/language-configuration-schema.json +24 -0
  34. package/editors/vscode/package.json +172 -12
  35. package/editors/vscode/snippets/axiom.json +12 -0
  36. package/editors/vscode/snippets/bloom.json +12 -0
  37. package/editors/vscode/snippets/helm.json +12 -0
  38. package/editors/vscode/snippets/hive.json +12 -0
  39. package/editors/vscode/snippets/mint.json +12 -0
  40. package/editors/vscode/snippets/shift.json +17 -0
  41. package/editors/vscode/syntaxes/axiom.tmLanguage.json +5 -0
  42. package/editors/vscode/syntaxes/bloom.tmLanguage.json +5 -0
  43. package/editors/vscode/syntaxes/helm.tmLanguage.json +5 -0
  44. package/editors/vscode/syntaxes/hive.tmLanguage.json +5 -0
  45. package/editors/vscode/syntaxes/mint.tmLanguage.json +5 -0
  46. package/editors/vscode/syntaxes/schema.tmLanguage.json +89 -0
  47. package/editors/vscode/syntaxes/shift.tmLanguage.json +5 -0
  48. package/examples/game/.cluaupp/compile-cache/ReplicatedStorage__Shared__Constants__Datas__TemplateData.clh.json +1 -0
  49. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Boot__DataBoot.server.clpp.json +1 -0
  50. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Configuration__ServerConfig.clp.json +1 -0
  51. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__Guard.server.clpp.json +1 -0
  52. package/examples/game/.cluaupp/compile-cache/ServerScriptService__Handlers__PlayerHandler.server.clpp.json +1 -0
  53. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterCharacterScripts__Character__CharacterReady.client.clpp.json +1 -0
  54. package/examples/game/.cluaupp/compile-cache/StarterPlayer__StarterPlayerScripts__Controllers__DataController.client.clpp.json +1 -0
  55. package/examples/game/.cluaupp/compile-cache/index.json +12 -0
  56. package/examples/game/.cluaupp/datamodel-profile.json +94 -0
  57. package/examples/game/.vscode/settings.json +12 -1
  58. package/examples/game/include/clpp/datatypes.clh +337 -373
  59. package/examples/game/include/clpp/generated/datamodel.clh +25 -0
  60. package/examples/game/include/clpp/generated/enums.clh +1 -1
  61. package/examples/game/include/clpp/generated/instances.clh +41135 -41064
  62. package/examples/game/include/clpp/libs/axiom.clh +1 -1
  63. package/examples/game/include/clpp/libs/math.clh +14 -0
  64. package/examples/game/include/clpp/libs/spring.clh +17 -0
  65. package/examples/game/include/clpp/libs/ward.clh +1 -0
  66. package/examples/game/include/clpp/roblox.clh +3 -4
  67. package/examples/game/libs/ArrayIndexer/init.luau +209 -0
  68. package/examples/game/libs/Axiom/init.luau +608 -0
  69. package/examples/game/libs/Bloom/init.luau +433 -0
  70. package/examples/game/libs/Coil/init.luau +215 -0
  71. package/examples/game/libs/Crest/init.luau +426 -0
  72. package/examples/game/libs/Echo/init.luau +417 -0
  73. package/examples/game/libs/Ember/init.luau +365 -0
  74. package/examples/game/libs/Flare/init.luau +717 -0
  75. package/examples/game/libs/Gleam/init.luau +729 -0
  76. package/examples/game/libs/Guide/init.luau +215 -0
  77. package/examples/game/libs/Helm/init.luau +377 -0
  78. package/examples/game/libs/Hive/init.luau +241 -0
  79. package/examples/game/libs/Keep/Client.luau +114 -0
  80. package/examples/game/libs/Keep/Data.luau +883 -0
  81. package/examples/game/libs/Keep/Engine.luau +211 -0
  82. package/examples/game/libs/Keep/Enum.luau +6 -0
  83. package/examples/game/libs/Keep/Enums.luau +10 -0
  84. package/examples/game/libs/Keep/Path.luau +236 -0
  85. package/examples/game/libs/Keep/Replicator.luau +298 -0
  86. package/examples/game/libs/Keep/Server.luau +251 -0
  87. package/examples/game/libs/Keep/Store.luau +652 -0
  88. package/examples/game/libs/Keep/Trade.luau +455 -0
  89. package/examples/game/libs/Keep/init.luau +205 -0
  90. package/examples/game/libs/Lens/init.luau +609 -0
  91. package/examples/game/libs/Mint/init.luau +279 -0
  92. package/examples/game/libs/Net/init.luau +156 -0
  93. package/examples/game/libs/Net/src/codec.luau +224 -0
  94. package/examples/game/libs/Occlude/init.luau +117 -0
  95. package/examples/game/libs/Pin/init.luau +309 -0
  96. package/examples/game/libs/Promise/LICENSE +21 -0
  97. package/examples/game/libs/Promise/_impl/LICENSE +21 -0
  98. package/examples/game/libs/Promise/_impl/init.lua +1991 -0
  99. package/examples/game/libs/Promise/init.lua +1990 -0
  100. package/examples/game/libs/Promise/init.luau +13 -0
  101. package/examples/game/libs/Promise/types.luau +46 -0
  102. package/examples/game/libs/Roster/init.luau +686 -0
  103. package/examples/game/libs/SOURCES.md +31 -0
  104. package/examples/game/libs/Shift/init.luau +238 -0
  105. package/examples/game/libs/Spark/init.luau +487 -0
  106. package/examples/game/libs/Stage/init.luau +178 -0
  107. package/examples/game/libs/Sweep/init.luau +259 -0
  108. package/examples/game/libs/Trace/init.luau +213 -0
  109. package/examples/game/libs/Ward/init.luau +211 -0
  110. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +29 -0
  111. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +13 -0
  112. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +83 -0
  113. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +13 -0
  114. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +18 -0
  115. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +13 -0
  116. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +14 -0
  117. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +13 -0
  118. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +15 -0
  119. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +13 -0
  120. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +50 -0
  121. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +13 -0
  122. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +12 -0
  123. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +13 -0
  124. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +16 -0
  125. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +13 -0
  126. package/examples/game/src/ReplicatedStorage/Shared/Net/Net.clh +26 -0
  127. package/examples/game/src/ServerScriptService/Boot/DataBoot.server.clpp +1 -1
  128. package/examples/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  129. package/examples/game/stylua.toml +9 -0
  130. package/generated/api/build-profile.js +115 -0
  131. package/generated/api/cache.js +44 -0
  132. package/generated/api/coverage.js +32 -0
  133. package/generated/api/diff.js +125 -0
  134. package/generated/api/generators/clpp-headers.js +353 -0
  135. package/generated/api/generators/docs-reference.js +7 -0
  136. package/generated/api/generators/lsp-index.js +81 -0
  137. package/generated/api/generators/luau-defs.js +94 -0
  138. package/generated/api/ide.js +76 -0
  139. package/generated/api/identifier.js +47 -0
  140. package/generated/api/index.js +324 -0
  141. package/generated/api/loader.js +57 -0
  142. package/generated/api/merge.js +88 -0
  143. package/generated/api/model.js +5 -0
  144. package/generated/api/normalize.js +231 -0
  145. package/generated/api/overrides-validate.js +58 -0
  146. package/generated/api/perf.js +12 -0
  147. package/generated/api/registry.js +136 -0
  148. package/generated/api/release.js +44 -0
  149. package/generated/api/resolver.js +250 -0
  150. package/generated/api/sources/aux-types-diff.js +75 -0
  151. package/generated/api/sources/client-tracker.js +11 -0
  152. package/generated/api/sources/creator-docs.js +42 -0
  153. package/generated/api/sources/luau-types.js +34 -0
  154. package/generated/api/sources/mini-dump.js +17 -0
  155. package/generated/api/sources/studio-api.js +8 -0
  156. package/generated/api/sources/studio-apiv2.js +11 -0
  157. package/generated/api/sources/studio-full-api.js +8 -0
  158. package/generated/api/studio-smoke.js +80 -0
  159. package/generated/api/type-parse.js +49 -0
  160. package/generated/api/understander.js +51 -0
  161. package/generated/api/validate.js +135 -0
  162. package/generated/api-cli.js +421 -0
  163. package/generated/cli.js +16 -5
  164. package/generated/clpp/contract.js +3 -3
  165. package/generated/clpp/format-luau.js +236 -0
  166. package/generated/clpp/index.js +13 -1
  167. package/generated/clpp/modules.js +227 -0
  168. package/generated/clpp/postprocess.js +86 -5
  169. package/generated/clpp/rewrite-janitor.js +145 -0
  170. package/generated/clpp/runner.js +14 -2
  171. package/generated/compile.js +82 -0
  172. package/generated/flare/parse.js +12 -1
  173. package/generated/intellisense.js +57 -1
  174. package/generated/native/index.js +217 -16
  175. package/generated/target/authority-check.js +136 -0
  176. package/generated/target/authority-graph.js +74 -0
  177. package/generated/target/build-cache.js +112 -0
  178. package/generated/target/capabilities.js +89 -0
  179. package/generated/target/capability-profile.js +30 -0
  180. package/generated/target/component-contracts.js +60 -0
  181. package/generated/target/context-check.js +160 -0
  182. package/generated/target/datamodel-check.js +170 -0
  183. package/generated/target/datamodel-generate.js +74 -0
  184. package/generated/target/datamodel.js +233 -0
  185. package/generated/target/diagnostics.js +63 -0
  186. package/generated/target/doctor.js +152 -0
  187. package/generated/target/flare-version.js +58 -0
  188. package/generated/target/get-service.js +69 -0
  189. package/generated/target/lifetime-check.js +47 -0
  190. package/generated/target/luau-stamp.js +39 -0
  191. package/generated/target/optimizer-advise.js +88 -0
  192. package/generated/target/optimizer-apply.js +44 -0
  193. package/generated/target/optimizer-soa.js +254 -0
  194. package/generated/target/parallel-check.js +136 -0
  195. package/generated/target/pgo.js +148 -0
  196. package/generated/target/project-docs.js +69 -0
  197. package/generated/target/project-graph.js +71 -0
  198. package/generated/target/roblox.js +63 -0
  199. package/generated/target/security-check.js +41 -0
  200. package/generated/target/source-map.js +25 -0
  201. package/generated/target/studio-bridge.js +112 -0
  202. package/generated/utils/project.js +178 -8
  203. package/generated/utils/rojo-mapper.js +11 -3
  204. package/include/clpp/datatypes.clh +337 -373
  205. package/include/clpp/generated/enums.clh +1 -1
  206. package/include/clpp/generated/instances.clh +41135 -41064
  207. package/include/clpp/libs/axiom.clh +1 -1
  208. package/include/clpp/libs/hive.clh +1 -0
  209. package/include/clpp/libs/keep.clh +2 -0
  210. package/include/clpp/libs/math.clh +14 -0
  211. package/include/clpp/libs/spring.clh +17 -0
  212. package/include/clpp/libs/ward.clh +1 -0
  213. package/include/clpp/roblox.clh +3 -4
  214. package/package.json +10 -3
  215. package/plugins/CluauppNav/Plugin.luau +207 -0
  216. package/plugins/CluauppNav/ProfileLogger.luau +27 -0
  217. package/plugins/CluauppNav/README.md +24 -0
  218. package/runtime/Axiom/init.luau +10 -7
  219. package/runtime/Coil/init.luau +8 -2
  220. package/runtime/Crest/init.luau +1 -0
  221. package/runtime/Flare/init.luau +2 -1
  222. package/runtime/Gleam/init.luau +15 -4
  223. package/runtime/Hive/init.luau +36 -14
  224. package/runtime/Pin/init.luau +5 -2
  225. package/runtime/Roster/init.luau +2 -0
  226. package/runtime/Spark/init.luau +3 -0
  227. package/runtime/Sweep/init.luau +2 -0
  228. package/runtime/Trace/init.luau +3 -0
  229. package/runtime/Ward/init.luau +38 -5
  230. package/scripts/postinstall-editor.js +17 -0
  231. package/skills/README.md +13 -0
  232. package/skills/clpp-hive-flare/SKILL.md +79 -0
  233. package/skills/clpp-language/SKILL.md +123 -0
  234. package/skills/clpp-language/compiler.md +89 -0
  235. package/skills/clpp-style/SKILL.md +95 -0
  236. package/src/api/build-profile.ts +138 -0
  237. package/src/api/cache.ts +45 -0
  238. package/src/api/coverage.ts +46 -0
  239. package/src/api/diff.ts +143 -0
  240. package/src/api/generators/clpp-headers.ts +377 -0
  241. package/src/api/generators/docs-reference.ts +11 -0
  242. package/src/api/generators/lsp-index.ts +106 -0
  243. package/src/api/generators/luau-defs.ts +98 -0
  244. package/src/api/ide.ts +87 -0
  245. package/src/api/identifier.ts +47 -0
  246. package/src/api/index.ts +269 -0
  247. package/src/api/loader.ts +60 -0
  248. package/src/api/merge.ts +126 -0
  249. package/src/api/model.ts +283 -0
  250. package/src/api/normalize.ts +257 -0
  251. package/src/api/overrides-validate.ts +58 -0
  252. package/src/api/perf.ts +15 -0
  253. package/src/api/registry.ts +162 -0
  254. package/src/api/release.ts +47 -0
  255. package/src/api/resolver.ts +255 -0
  256. package/src/api/sources/aux-types-diff.ts +81 -0
  257. package/src/api/sources/client-tracker.ts +10 -0
  258. package/src/api/sources/creator-docs.ts +37 -0
  259. package/src/api/sources/luau-types.ts +30 -0
  260. package/src/api/sources/mini-dump.ts +50 -0
  261. package/src/api/sources/studio-api.ts +7 -0
  262. package/src/api/sources/studio-apiv2.ts +10 -0
  263. package/src/api/sources/studio-full-api.ts +7 -0
  264. package/src/api/studio-smoke.ts +82 -0
  265. package/src/api/type-parse.ts +48 -0
  266. package/src/api/understander.ts +72 -0
  267. package/src/api/validate.ts +160 -0
  268. package/src/api-cli.ts +493 -0
  269. package/src/api.generated.js +37 -22
  270. package/src/cli.ts +21 -6
  271. package/src/clpp/contract.ts +34 -3
  272. package/src/clpp/format-luau.ts +262 -0
  273. package/src/clpp/index.ts +13 -2
  274. package/src/clpp/modules.ts +252 -0
  275. package/src/clpp/postprocess.ts +100 -5
  276. package/src/clpp/rewrite-janitor.ts +156 -0
  277. package/src/clpp/runner.ts +14 -2
  278. package/src/compile.ts +87 -0
  279. package/src/flare/parse.ts +14 -1
  280. package/src/flare/types.ts +2 -0
  281. package/src/intellisense.ts +58 -1
  282. package/src/native/index.ts +225 -16
  283. package/src/target/authority-check.ts +162 -0
  284. package/src/target/authority-graph.ts +80 -0
  285. package/src/target/build-cache.ts +129 -0
  286. package/src/target/capabilities.ts +115 -0
  287. package/src/target/capability-profile.ts +25 -0
  288. package/src/target/component-contracts.ts +64 -0
  289. package/src/target/context-check.ts +177 -0
  290. package/src/target/datamodel-check.ts +188 -0
  291. package/src/target/datamodel-generate.ts +78 -0
  292. package/src/target/datamodel.ts +261 -0
  293. package/src/target/diagnostics.ts +67 -0
  294. package/src/target/doctor.ts +171 -0
  295. package/src/target/flare-version.ts +61 -0
  296. package/src/target/get-service.ts +85 -0
  297. package/src/target/lifetime-check.ts +45 -0
  298. package/src/target/luau-stamp.ts +33 -0
  299. package/src/target/optimizer-advise.ts +93 -0
  300. package/src/target/optimizer-apply.ts +63 -0
  301. package/src/target/optimizer-soa.ts +270 -0
  302. package/src/target/parallel-check.ts +135 -0
  303. package/src/target/pgo.ts +157 -0
  304. package/src/target/project-docs.ts +68 -0
  305. package/src/target/project-graph.ts +75 -0
  306. package/src/target/roblox.ts +78 -0
  307. package/src/target/security-check.ts +40 -0
  308. package/src/target/source-map.ts +36 -0
  309. package/src/target/studio-bridge.ts +140 -0
  310. package/src/types.ts +14 -0
  311. package/src/utils/project.ts +183 -9
  312. package/src/utils/rojo-mapper.ts +12 -3
  313. package/stylua.toml +9 -0
  314. package/templates/game/.vscode/settings.json +7 -1
  315. package/templates/game/include/clpp/datatypes.clh +337 -373
  316. package/templates/game/include/clpp/generated/enums.clh +1 -1
  317. package/templates/game/include/clpp/generated/instances.clh +41135 -41064
  318. package/templates/game/include/clpp/libs/axiom.clh +1 -1
  319. package/templates/game/include/clpp/libs/ward.clh +1 -0
  320. package/templates/game/include/clpp/roblox.clh +3 -4
  321. package/templates/game/src/ServerScriptService/Boot/DataBoot.server.clpp +1 -1
  322. package/templates/game/src/ServerScriptService/Handlers/PlayerHandler.server.clpp +1 -1
  323. package/templates/game/stylua.toml +9 -0
@@ -0,0 +1,298 @@
1
+ --!native
2
+ --!optimize 2
3
+ --!strict
4
+ -- Keep replicator — tagged buffers (Ready / Snapshot / Delta). No JSON, no QuickNet.
5
+
6
+ local RunService = game:GetService("RunService")
7
+ local Spark = require(script.Parent.Parent.Spark)
8
+ local Ward = require(script.Parent.Parent.Ward)
9
+
10
+ local TAG = {
11
+ Ready = 1,
12
+ Snapshot = 2,
13
+ Delta = 3,
14
+ Init = 4,
15
+ Set = 5,
16
+ ArrayInsert = 6,
17
+ ArrayRemove = 7,
18
+ TransientSet = 8,
19
+ }
20
+
21
+ local ACTION_TAG = {
22
+ i = TAG.Init,
23
+ s = TAG.Set,
24
+ ai = TAG.ArrayInsert,
25
+ ar = TAG.ArrayRemove,
26
+ ts = TAG.TransientSet,
27
+ ready = TAG.Ready,
28
+ snapshot = TAG.Snapshot,
29
+ delta = TAG.Delta,
30
+ }
31
+
32
+ local TAG_ACTION = {}
33
+ for name, id in ACTION_TAG do
34
+ TAG_ACTION[id] = name
35
+ end
36
+
37
+ local TYPE = { Nil = 0, Bool = 1, Number = 2, String = 3, Table = 4 }
38
+
39
+ local function grow(buf: buffer, need: number): buffer
40
+ if buffer.len(buf) >= need then
41
+ return buf
42
+ end
43
+ local nextBuf = buffer.create(math.max(need, buffer.len(buf) * 2))
44
+ buffer.copy(nextBuf, 0, buf, 0, buffer.len(buf))
45
+ return nextBuf
46
+ end
47
+
48
+ local function writeString(buf: buffer, cursor: number, text: string): (buffer, number)
49
+ buf = grow(buf, cursor + 2 + #text)
50
+ buffer.writeu16(buf, cursor, #text)
51
+ buffer.writestring(buf, cursor + 2, text)
52
+ return buf, cursor + 2 + #text
53
+ end
54
+
55
+ local function readString(buf: buffer, cursor: number): (string, number)
56
+ local length = buffer.readu16(buf, cursor)
57
+ return buffer.readstring(buf, cursor + 2, length), cursor + 2 + length
58
+ end
59
+
60
+ local writeValue: (buffer, number, any) -> (buffer, number)
61
+ local readValue: (buffer, number) -> (any, number)
62
+
63
+ writeValue = function(buf: buffer, cursor: number, value: any): (buffer, number)
64
+ local kind = typeof(value)
65
+ buf = grow(buf, cursor + 16)
66
+ if value == nil then
67
+ buffer.writeu8(buf, cursor, TYPE.Nil)
68
+ return buf, cursor + 1
69
+ end
70
+ if kind == "boolean" then
71
+ buffer.writeu8(buf, cursor, TYPE.Bool)
72
+ buffer.writeu8(buf, cursor + 1, if value then 1 else 0)
73
+ return buf, cursor + 2
74
+ end
75
+ if kind == "number" then
76
+ buffer.writeu8(buf, cursor, TYPE.Number)
77
+ buffer.writef64(buf, cursor + 1, value)
78
+ return buf, cursor + 9
79
+ end
80
+ if kind == "string" then
81
+ buffer.writeu8(buf, cursor, TYPE.String)
82
+ return writeString(buf, cursor + 1, value)
83
+ end
84
+ if kind == "table" then
85
+ buffer.writeu8(buf, cursor, TYPE.Table)
86
+ cursor += 1
87
+ local count = 0
88
+ for _ in value do
89
+ count += 1
90
+ end
91
+ buf = grow(buf, cursor + 2)
92
+ buffer.writeu16(buf, cursor, count)
93
+ cursor += 2
94
+ for key, item in value do
95
+ buf, cursor = writeValue(buf, cursor, key)
96
+ buf, cursor = writeValue(buf, cursor, item)
97
+ end
98
+ return buf, cursor
99
+ end
100
+ buffer.writeu8(buf, cursor, TYPE.Nil)
101
+ return buf, cursor + 1
102
+ end
103
+
104
+ readValue = function(buf: buffer, cursor: number): (any, number)
105
+ local kind = buffer.readu8(buf, cursor)
106
+ cursor += 1
107
+ if kind == TYPE.Nil then
108
+ return nil, cursor
109
+ end
110
+ if kind == TYPE.Bool then
111
+ return buffer.readu8(buf, cursor) == 1, cursor + 1
112
+ end
113
+ if kind == TYPE.Number then
114
+ return buffer.readf64(buf, cursor), cursor + 8
115
+ end
116
+ if kind == TYPE.String then
117
+ return readString(buf, cursor)
118
+ end
119
+ if kind == TYPE.Table then
120
+ local count = buffer.readu16(buf, cursor)
121
+ cursor += 2
122
+ local out = {}
123
+ for _ = 1, count do
124
+ local key
125
+ key, cursor = readValue(buf, cursor)
126
+ local item
127
+ item, cursor = readValue(buf, cursor)
128
+ out[key] = item
129
+ end
130
+ return out, cursor
131
+ end
132
+ return nil, cursor
133
+ end
134
+
135
+ local function pack(action: string, path: any, payload: { any }): buffer
136
+ local buf = buffer.create(64)
137
+ buffer.writeu8(buf, 0, ACTION_TAG[action] or TAG.Delta)
138
+ local cursor = 1
139
+ buf, cursor = writeValue(buf, cursor, path)
140
+ buf, cursor = writeValue(buf, cursor, payload)
141
+ local trimmed = buffer.create(cursor)
142
+ buffer.copy(trimmed, 0, buf, 0, cursor)
143
+ return trimmed
144
+ end
145
+
146
+ local function unpackPacket(buf: buffer): (string, any, { any })
147
+ local tag = buffer.readu8(buf, 0)
148
+ local path
149
+ local cursor
150
+ path, cursor = readValue(buf, 1)
151
+ local payload
152
+ payload, cursor = readValue(buf, cursor)
153
+ return TAG_ACTION[tag] or "s", path, if typeof(payload) == "table" then payload else { payload }
154
+ end
155
+
156
+ local function folder(): Folder
157
+ local rs = game:GetService("ReplicatedStorage")
158
+ local existing = rs:FindFirstChild("KeepNet")
159
+ if existing and existing:IsA("Folder") then
160
+ return existing
161
+ end
162
+ local created = Instance.new("Folder")
163
+ created.Name = "KeepNet"
164
+ created.Parent = rs
165
+ local reliable = Instance.new("RemoteEvent")
166
+ reliable.Name = "Reliable"
167
+ reliable.Parent = created
168
+ return created
169
+ end
170
+
171
+ local net = folder()
172
+ local remote = net:WaitForChild("Reliable") :: RemoteEvent
173
+
174
+ local function emptyStats()
175
+ return {
176
+ Bytes = 0,
177
+ Messages = 0,
178
+ LastPacketBytes = 0,
179
+ LastUtilization = 0,
180
+ TotalBytes = 0,
181
+ TotalMessages = 0,
182
+ ByPlayer = {},
183
+ }
184
+ end
185
+
186
+ local Server = {
187
+ OnReady = Spark.new(),
188
+ BufferChanged = Spark.new(),
189
+ _stats = emptyStats(),
190
+ _handlers = {} :: { [string]: (...any) -> () },
191
+ _ready = {} :: { [Player]: boolean },
192
+ }
193
+
194
+ local Client = {
195
+ OnReady = Spark.new(),
196
+ BufferChanged = Spark.new(),
197
+ _stats = emptyStats(),
198
+ _handlers = {} :: { [string]: (...any) -> () },
199
+ }
200
+
201
+ if RunService:IsServer() then
202
+ remote.OnServerEvent:Connect(function(player: Player, packed: buffer?)
203
+ if typeof(packed) ~= "buffer" then
204
+ Ward.Strike(player, "keep:type")
205
+ return
206
+ end
207
+ if not Ward.Packet(player, buffer.len(packed), 256) then
208
+ return
209
+ end
210
+ if not Ward.Allow(player, "keep", 4, 8) then
211
+ return
212
+ end
213
+ local ok, action = pcall(unpackPacket, packed)
214
+ if not ok or action ~= "ready" then
215
+ Ward.Strike(player, "keep:action")
216
+ return
217
+ end
218
+ if Server._ready[player] then
219
+ return
220
+ end
221
+ Server._ready[player] = true
222
+ Server.OnReady:Fire(player)
223
+ end)
224
+
225
+ function Server:On(action: string, handler: (...any) -> ())
226
+ self._handlers[action] = handler
227
+ end
228
+
229
+ function Server:Send(player: Player, action: string, path: any, ...)
230
+ local payload = table.pack(...)
231
+ local packed = pack(action, path, payload)
232
+ local bytes = buffer.len(packed)
233
+ local byPlayer = self._stats.ByPlayer[player]
234
+ if not byPlayer then
235
+ byPlayer = emptyStats()
236
+ self._stats.ByPlayer[player] = byPlayer
237
+ end
238
+ byPlayer.Bytes += bytes
239
+ byPlayer.Messages += 1
240
+ byPlayer.LastPacketBytes = bytes
241
+ byPlayer.LastUtilization = math.clamp(bytes / 1024, 0, 1)
242
+ self._stats.TotalBytes += bytes
243
+ self._stats.TotalMessages += 1
244
+ self._stats.LastPacketBytes = bytes
245
+ remote:FireClient(player, packed)
246
+ end
247
+
248
+ function Server:GetBufferStats(player: Player?)
249
+ if player then
250
+ return self._stats.ByPlayer[player]
251
+ end
252
+ return self._stats
253
+ end
254
+
255
+ function Server:ForgetPlayer(player: Player)
256
+ self._stats.ByPlayer[player] = nil
257
+ self._ready[player] = nil
258
+ end
259
+
260
+ function Server:Destroy()
261
+ Server.OnReady:Destroy()
262
+ Server.BufferChanged:Destroy()
263
+ end
264
+ else
265
+ function Client:On(action: string, handler: (...any) -> ())
266
+ self._handlers[action] = handler
267
+ end
268
+
269
+ function Client:NotifyReady()
270
+ remote:FireServer(pack("ready", {}, {}))
271
+ end
272
+
273
+ remote.OnClientEvent:Connect(function(packed: buffer)
274
+ local action, path, payload = unpackPacket(packed)
275
+ Client._stats.LastPacketBytes = buffer.len(packed)
276
+ Client._stats.Bytes += Client._stats.LastPacketBytes
277
+ Client._stats.Messages += 1
278
+ Client.BufferChanged:Fire(Client._stats)
279
+ local handler = Client._handlers[action]
280
+ if handler then
281
+ handler(path, table.unpack(payload, 1, payload.n or #payload))
282
+ end
283
+ if action == "ready" or action == "i" then
284
+ Client.OnReady:Fire()
285
+ end
286
+ end)
287
+
288
+ function Client:GetBufferStats()
289
+ return Client._stats
290
+ end
291
+
292
+ function Client:Destroy()
293
+ Client.OnReady:Destroy()
294
+ Client.BufferChanged:Destroy()
295
+ end
296
+ end
297
+
298
+ return { Server = Server, Client = Client, TAG = TAG }
@@ -0,0 +1,251 @@
1
+ --!strict
2
+ -- Compiled by CL++ — C++ × Luau
3
+
4
+ const Sweep = require(script.Parent.Parent.Sweep)
5
+ const Engine = require(script.Parent.Engine)
6
+
7
+ local DataServiceServer = {}
8
+
9
+ DataServiceServer.janitor = nil
10
+
11
+ DataServiceServer.initialized = nil
12
+
13
+ DataServiceServer.Paths = nil
14
+
15
+ DataServiceServer.options = nil
16
+
17
+ DataServiceServer.store = nil
18
+
19
+ DataServiceServer.sessions = nil
20
+
21
+ DataServiceServer.profiles = nil
22
+
23
+ DataServiceServer.sessionJanitors = nil
24
+
25
+ DataServiceServer.waiters = nil
26
+
27
+ DataServiceServer.ready = nil
28
+
29
+ DataServiceServer.excluded = nil
30
+
31
+ const DEFAULT_KEY_PREFIX: string = "Player_"
32
+
33
+ function DataServiceServer:Init(options: DataServiceOptions): DataServiceServer
34
+ local runService: RunService = game:GetService("RunService")
35
+ if runService:IsServer() == false then
36
+ error("DataService.Server may only be used on the server")
37
+ return self
38
+ end
39
+ if self.initialized then
40
+ error("DataService.Server already initialized")
41
+ return self
42
+ end
43
+ if not (options.Template ~= nil) then
44
+ error("DataService.Server.Init requires options.Template")
45
+ return self
46
+ end
47
+ self.initialized = true
48
+ self.options = options
49
+ self.janitor = Sweep.new()
50
+ self.Paths = Engine:createTemplatePaths(options.Template)
51
+ local storeName: string = "PlayerData"
52
+ if options.StoreName ~= nil then
53
+ storeName = options.StoreName
54
+ end
55
+ local created = Engine:profileStoreNew(storeName, options.Template)
56
+ if options.UseMock then
57
+ self.store = created.Mock
58
+ else
59
+ self.store = created
60
+ end
61
+ self.sessions = Engine:mapNew()
62
+ self.profiles = Engine:mapNew()
63
+ self.sessionJanitors = Engine:mapNew()
64
+ self.waiters = Engine:mapNew()
65
+ self.ready = Engine:mapNew()
66
+ self.excluded = Engine:mapNew()
67
+ local excludes: {DataPath} = options.Exclude
68
+ if excludes ~= nil then
69
+ for _, path in excludes do
70
+ local key: string = Engine:toKey(path)
71
+ Engine:mapSet(self.excluded, key, true)
72
+ end
73
+ end
74
+ local players: Players = game:GetService("Players")
75
+ self.janitor:Add(Engine.Replicator.OnReady:Connect(function(player: Player)
76
+ Engine:mapSet(self.ready, player, true)
77
+ if Engine:mapGet(self.sessions, player) ~= nil then
78
+ self:SendInit(player)
79
+ end
80
+ end), "Disconnect")
81
+ for _, player in players:GetPlayers() do
82
+ task.spawn(function()
83
+ self:OnAdded(player)
84
+ end)
85
+ end
86
+ self.janitor:Add(players.PlayerAdded:Connect(function(...) self:OnAdded(...) end), "Disconnect")
87
+ self.janitor:Add(players.PlayerRemoving:Connect(function(...) self:OnRemoving(...) end), "Disconnect")
88
+ return self
89
+ end
90
+
91
+ function DataServiceServer:ProfileKey(player: Player): string
92
+ local prefix: string = self.options.KeyPrefix
93
+ if prefix == nil then
94
+ prefix = DEFAULT_KEY_PREFIX
95
+ end
96
+ return prefix .. tostring(player.UserId)
97
+ end
98
+
99
+ function DataServiceServer:SendInit(player: Player)
100
+ local session: Data = Engine:mapGet(self.sessions, player)
101
+ if not (session ~= nil) then
102
+ return
103
+ end
104
+ local snapshot = Engine:buildSnapshot(self.excluded, session:Get(), Engine:emptyPath())
105
+ Engine:replicatorSend(player, Engine.Enums.Init, nil, snapshot)
106
+ end
107
+
108
+ function DataServiceServer:OnAdded(player: Player)
109
+ if not (player ~= nil) then
110
+ return
111
+ end
112
+ local existingJanitor = Engine:mapGet(self.sessionJanitors, player)
113
+ if existingJanitor ~= nil then
114
+ existingJanitor:Cleanup()
115
+ end
116
+ local sessionJanitor = Sweep.new()
117
+ Engine:mapSet(self.sessionJanitors, player, sessionJanitor)
118
+ local players: Players = game:GetService("Players")
119
+ local key: string = self:ProfileKey(player)
120
+ local profile = Engine:startSession(self.store, key, player, players)
121
+ if profile == nil then
122
+ player:Kick("Data load failed - please rejoin")
123
+ return
124
+ end
125
+ profile:AddUserId(player.UserId)
126
+ profile:Reconcile()
127
+ local sessionEndConnection = profile.OnSessionEnd:Connect(function()
128
+ Engine:mapClear(self.profiles, player)
129
+ if player.Parent ~= nil then
130
+ player:Kick("Data session ended - please rejoin")
131
+ end
132
+ end)
133
+ sessionJanitor:Add(function()
134
+ sessionEndConnection:Disconnect()
135
+ end, true)
136
+ if player:IsDescendantOf(players) == false then
137
+ Engine:abortActiveTrade(profile)
138
+ profile:EndSession()
139
+ return
140
+ end
141
+ Engine:mapSet(self.profiles, player, profile)
142
+ local strictPaths: boolean = true
143
+ if self.options.StrictPaths == false then
144
+ strictPaths = false
145
+ end
146
+ local autoCreate: boolean = false
147
+ if self.options.AutoCreateMissingTables then
148
+ autoCreate = true
149
+ end
150
+ local tmpl = self.options.Template
151
+ if tmpl == nil then
152
+ tmpl = profile.Data
153
+ end
154
+ local session: Data = Engine:dataNew(profile.Data, true, strictPaths, autoCreate, tmpl)
155
+ Engine:mapSet(self.sessions, player, session)
156
+ local dataChangedConnection = Engine:watchData(session, player, self.ready, self.excluded)
157
+ sessionJanitor:Add(function()
158
+ dataChangedConnection:Disconnect()
159
+ end, true)
160
+ local sig = Engine:mapGet(self.waiters, player)
161
+ if sig ~= nil then
162
+ sig:Fire()
163
+ sig:Destroy()
164
+ Engine:mapClear(self.waiters, player)
165
+ end
166
+ if Engine:mapGet(self.ready, player) then
167
+ self:SendInit(player)
168
+ end
169
+ end
170
+
171
+ function DataServiceServer:OnRemoving(player: Player)
172
+ local sessionJanitor = Engine:mapGet(self.sessionJanitors, player)
173
+ if sessionJanitor ~= nil then
174
+ sessionJanitor:Cleanup()
175
+ Engine:mapClear(self.sessionJanitors, player)
176
+ end
177
+ local session: Data = Engine:mapGet(self.sessions, player)
178
+ if session ~= nil then
179
+ session:Destroy()
180
+ Engine:mapClear(self.sessions, player)
181
+ end
182
+ local profile = Engine:mapGet(self.profiles, player)
183
+ if profile ~= nil then
184
+ Engine:abortActiveTrade(profile)
185
+ profile:EndSession()
186
+ Engine:mapClear(self.profiles, player)
187
+ end
188
+ Engine:replicatorForgetPlayer(player)
189
+ Engine:mapClear(self.ready, player)
190
+ local sig = Engine:mapGet(self.waiters, player)
191
+ if sig ~= nil then
192
+ sig:Destroy()
193
+ Engine:mapClear(self.waiters, player)
194
+ end
195
+ end
196
+
197
+ function DataServiceServer:WaitFor(player: Player): Data
198
+ local loaded: Data = Engine:mapGet(self.sessions, player)
199
+ if loaded ~= nil then
200
+ return loaded
201
+ end
202
+ local players: Players = game:GetService("Players")
203
+ if not (player:IsDescendantOf(players)) then
204
+ error("DataService.Server.WaitFor called for a player that is not in Players")
205
+ return nil
206
+ end
207
+ local sig = Engine:mapGet(self.waiters, player)
208
+ if sig == nil then
209
+ sig = Engine:signalNew()
210
+ Engine:mapSet(self.waiters, player, sig)
211
+ end
212
+ sig:Wait()
213
+ local after: Data = Engine:mapGet(self.sessions, player)
214
+ if not (after ~= nil) then
215
+ error("DataService.Server: player data was not available after wait")
216
+ return nil
217
+ end
218
+ return after
219
+ end
220
+
221
+ function DataServiceServer:Get(player: Player): Data
222
+ return Engine:mapGet(self.sessions, player)
223
+ end
224
+
225
+ function DataServiceServer:HasData(player: Player): boolean
226
+ return Engine:mapGet(self.sessions, player) ~= nil
227
+ end
228
+
229
+ function DataServiceServer:GetProfile(player: Player): DataProfile
230
+ return Engine:mapGet(self.profiles, player)
231
+ end
232
+
233
+ function DataServiceServer:GetBufferStats(player: Player): DataBufferStats
234
+ return Engine:replicatorGetBufferStats(player)
235
+ end
236
+
237
+ function DataServiceServer:Destroy()
238
+ local players: Players = game:GetService("Players")
239
+ for _, player in players:GetPlayers() do
240
+ if Engine:mapGet(self.sessions, player) ~= nil then
241
+ self:OnRemoving(player)
242
+ end
243
+ end
244
+ if self.janitor ~= nil then
245
+ self.janitor:Cleanup()
246
+ self.janitor = nil
247
+ end
248
+ Engine:replicatorDestroy()
249
+ end
250
+
251
+ return DataServiceServer