cluaupp 1.5.2 → 2.0.0-beta.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.
Files changed (210) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +29 -41
  3. package/api/generated/bench-latest.json +43 -21
  4. package/api/generated/lsp-index.json +1 -1
  5. package/api/manifests/roblox-target.manifest.json +5 -5
  6. package/api/normalized/roblox-target.profile.json +8729 -267
  7. package/api/roblox/luau-builtins.d.luau +185 -0
  8. package/api/roblox/surface.json +1 -0
  9. package/api/roblox-api.lock.json +11 -2
  10. package/bin/cluaupp.js +38 -0
  11. package/editors/vscode/README.md +1 -1
  12. package/editors/vscode/package.json +50 -15
  13. package/editors/vscode/snippets/flare.json +1 -1
  14. package/editors/vscode/snippets/hive.json +1 -1
  15. package/editors/vscode/syntaxes/clpp.tmLanguage.json +211 -0
  16. package/examples/README.md +9 -9
  17. package/examples/game/cluaupp.config.json +2 -2
  18. package/examples/game/default.project.json +4 -15
  19. package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau +8 -0
  20. package/examples/game/out/ReplicatedStorage/Shared/GameInfo.luau.map.json +13 -0
  21. package/examples/game/out/ServerScriptService/Leaderstats.server.luau +26 -0
  22. package/examples/game/out/ServerScriptService/Leaderstats.server.luau.map.json +13 -0
  23. package/examples/game/out/ServerScriptService/Main.server.luau +15 -0
  24. package/examples/game/out/ServerScriptService/Main.server.luau.map.json +13 -0
  25. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau +10 -0
  26. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Main.client.luau.map.json +13 -0
  27. package/examples/game/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
  28. package/examples/game/src/ServerScriptService/Leaderstats.server.clp +18 -0
  29. package/examples/game/src/ServerScriptService/Main.server.clp +9 -0
  30. package/examples/game/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
  31. package/generated/api/build-profile.js +1 -1
  32. package/generated/api/loader.js +2 -2
  33. package/generated/api/surface/build.js +328 -0
  34. package/generated/api/surface/luau-defs.js +595 -0
  35. package/generated/api/surface/model.js +8 -0
  36. package/generated/api-cli.js +2 -2
  37. package/generated/cli.js +18 -17
  38. package/generated/clpp/contract.js +6 -3
  39. package/generated/clpp/handshake.js +36 -0
  40. package/generated/clpp/modules.js +20 -9
  41. package/generated/clpp/runner.js +62 -31
  42. package/generated/compile.js +18 -1
  43. package/generated/compiler/ast.js +3 -0
  44. package/generated/compiler/checker/calls.js +999 -0
  45. package/generated/compiler/checker/checker.js +1215 -0
  46. package/generated/compiler/checker/exprs.js +791 -0
  47. package/generated/compiler/checker/flow.js +168 -0
  48. package/generated/compiler/checker/members.js +763 -0
  49. package/generated/compiler/checker/statements.js +792 -0
  50. package/generated/compiler/checker/symbols.js +90 -0
  51. package/generated/compiler/checker/typeops.js +348 -0
  52. package/generated/compiler/checker/yields.js +115 -0
  53. package/generated/compiler/diagnostics.js +138 -0
  54. package/generated/compiler/emit/emitter.js +2356 -0
  55. package/generated/compiler/emit/luau-types.js +137 -0
  56. package/generated/compiler/emit/names.js +130 -0
  57. package/generated/compiler/emit/runtime.js +432 -0
  58. package/generated/compiler/lexer.js +403 -0
  59. package/generated/compiler/parser.js +1881 -0
  60. package/generated/compiler/project.js +332 -0
  61. package/generated/compiler/roblox/api.js +388 -0
  62. package/generated/compiler/roblox/context.js +100 -0
  63. package/generated/compiler/source.js +59 -0
  64. package/generated/compiler/stdlib.js +232 -0
  65. package/generated/compiler/types.js +250 -0
  66. package/generated/intellisense.js +1 -15
  67. package/generated/lsp.js +1 -1
  68. package/generated/target/build-cache.js +4 -4
  69. package/generated/target/datamodel-generate.js +12 -0
  70. package/generated/target/gen-rojo-tree.js +15 -0
  71. package/generated/target/source-map.js +61 -8
  72. package/generated/target/studio-bridge.js +1 -0
  73. package/generated/utils/project.js +104 -31
  74. package/include/README.md +5 -0
  75. package/native/bin/.gitkeep +1 -0
  76. package/package.json +17 -6
  77. package/plugins/CluauppNav/Plugin.luau +28 -4
  78. package/rust/cluaupp/Cargo.lock +795 -0
  79. package/rust/cluaupp/Cargo.toml +17 -0
  80. package/rust/cluaupp/src/main.rs +717 -0
  81. package/scripts/postinstall-native.js +56 -0
  82. package/skills/README.md +3 -3
  83. package/skills/clpp-hive-flare/SKILL.md +30 -26
  84. package/skills/clpp-language/SKILL.md +67 -74
  85. package/skills/clpp-language/compiler.md +24 -36
  86. package/skills/clpp-style/SKILL.md +31 -44
  87. package/src/api/build-profile.ts +1 -1
  88. package/src/api/loader.ts +2 -2
  89. package/src/api/surface/build.ts +374 -0
  90. package/src/api/surface/luau-defs.ts +635 -0
  91. package/src/api/surface/model.ts +96 -0
  92. package/src/api-cli.ts +2 -2
  93. package/src/cli.ts +19 -18
  94. package/src/clpp/contract.ts +20 -3
  95. package/src/clpp/handshake.ts +25 -0
  96. package/src/clpp/modules.ts +17 -10
  97. package/src/clpp/runner.ts +52 -34
  98. package/src/compile.ts +20 -2
  99. package/src/compiler/ast.ts +336 -0
  100. package/src/compiler/checker/calls.ts +1025 -0
  101. package/src/compiler/checker/checker.ts +1352 -0
  102. package/src/compiler/checker/exprs.ts +805 -0
  103. package/src/compiler/checker/flow.ts +174 -0
  104. package/src/compiler/checker/members.ts +793 -0
  105. package/src/compiler/checker/statements.ts +802 -0
  106. package/src/compiler/checker/symbols.ts +219 -0
  107. package/src/compiler/checker/typeops.ts +355 -0
  108. package/src/compiler/checker/yields.ts +120 -0
  109. package/src/compiler/diagnostics.ts +163 -0
  110. package/src/compiler/emit/emitter.ts +2486 -0
  111. package/src/compiler/emit/luau-types.ts +143 -0
  112. package/src/compiler/emit/names.ts +130 -0
  113. package/src/compiler/emit/runtime.ts +438 -0
  114. package/src/compiler/lexer.ts +444 -0
  115. package/src/compiler/parser.ts +1943 -0
  116. package/src/compiler/project.ts +354 -0
  117. package/src/compiler/roblox/api.ts +408 -0
  118. package/src/compiler/roblox/context.ts +108 -0
  119. package/src/compiler/source.ts +67 -0
  120. package/src/compiler/stdlib.ts +256 -0
  121. package/src/compiler/types.ts +313 -0
  122. package/src/intellisense.ts +1 -13
  123. package/src/lsp.ts +1 -1
  124. package/src/target/build-cache.ts +5 -8
  125. package/src/target/datamodel-generate.ts +12 -1
  126. package/src/target/gen-rojo-tree.ts +15 -0
  127. package/src/target/source-map.ts +65 -27
  128. package/src/target/studio-bridge.ts +3 -0
  129. package/src/types.ts +3 -0
  130. package/src/utils/project.ts +99 -37
  131. package/templates/README.md +7 -0
  132. package/templates/{game → game-modern}/cluaupp.config.json +2 -2
  133. package/templates/{game → game-modern}/package.json +1 -2
  134. package/templates/game-modern/rokit.toml +2 -0
  135. package/templates/game-modern/src/ReplicatedStorage/Shared/GameInfo.clp +1 -0
  136. package/templates/game-modern/src/ServerScriptService/Handlers/Guard.server.clp +4 -0
  137. package/templates/game-modern/src/ServerScriptService/Main.server.clp +8 -0
  138. package/templates/game-modern/src/StarterPlayer/StarterPlayerScripts/Main.client.clp +4 -0
  139. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau +0 -29
  140. package/examples/game/out/ReplicatedStorage/Shared/Constants/Datas/TemplateData.luau.map.json +0 -13
  141. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau +0 -83
  142. package/examples/game/out/ReplicatedStorage/Shared/Net/Net.luau.map.json +0 -13
  143. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau +0 -18
  144. package/examples/game/out/ServerScriptService/Boot/DataBoot.server.luau.map.json +0 -13
  145. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau +0 -14
  146. package/examples/game/out/ServerScriptService/Configuration/ServerConfig.luau.map.json +0 -13
  147. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau +0 -15
  148. package/examples/game/out/ServerScriptService/Handlers/Guard.server.luau.map.json +0 -13
  149. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau +0 -50
  150. package/examples/game/out/ServerScriptService/Handlers/PlayerHandler.server.luau.map.json +0 -13
  151. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau +0 -12
  152. package/examples/game/out/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.luau.map.json +0 -13
  153. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau +0 -16
  154. package/examples/game/out/StarterPlayer/StarterPlayerScripts/Controllers/DataController.client.luau.map.json +0 -13
  155. package/examples/game/src/Client/Controllers/DataController.client.clpp +0 -7
  156. package/examples/game/src/Client/Main.client.clpp +0 -4
  157. package/examples/game/src/Declarations/Net.flare +0 -5
  158. package/examples/game/src/Include/GameTypes.clh +0 -40
  159. package/examples/game/src/Modules/Core/Guard.server.clpp +0 -7
  160. package/examples/game/src/Modules/Core/PlayerHandler.server.clpp +0 -23
  161. package/examples/game/src/Server/Boot/DataBoot.server.clpp +0 -13
  162. package/examples/game/src/Server/Main.server.clpp +0 -4
  163. package/templates/game/.clangd +0 -25
  164. package/templates/game/.vscode/extensions.json +0 -8
  165. package/templates/game/.vscode/settings.json +0 -17
  166. package/templates/game/Packages/.gitkeep +0 -0
  167. package/templates/game/compile_flags.txt +0 -6
  168. package/templates/game/default.project.json +0 -41
  169. package/templates/game/include/clpp/datatypes.clh +0 -575
  170. package/templates/game/include/clpp/generated/enums.clh +0 -4920
  171. package/templates/game/include/clpp/generated/instances.clh +0 -87182
  172. package/templates/game/include/clpp/libs/arrayindexer.clh +0 -12
  173. package/templates/game/include/clpp/libs/axiom.clh +0 -154
  174. package/templates/game/include/clpp/libs/bloom.clh +0 -58
  175. package/templates/game/include/clpp/libs/coil.clh +0 -37
  176. package/templates/game/include/clpp/libs/crest.clh +0 -22
  177. package/templates/game/include/clpp/libs/echo.clh +0 -52
  178. package/templates/game/include/clpp/libs/ember.clh +0 -17
  179. package/templates/game/include/clpp/libs/flare.clh +0 -65
  180. package/templates/game/include/clpp/libs/gleam.clh +0 -111
  181. package/templates/game/include/clpp/libs/guide.clh +0 -42
  182. package/templates/game/include/clpp/libs/helm.clh +0 -31
  183. package/templates/game/include/clpp/libs/hive.clh +0 -20
  184. package/templates/game/include/clpp/libs/keep.clh +0 -158
  185. package/templates/game/include/clpp/libs/lens.clh +0 -24
  186. package/templates/game/include/clpp/libs/mint.clh +0 -28
  187. package/templates/game/include/clpp/libs/net.clh +0 -31
  188. package/templates/game/include/clpp/libs/occlude.clh +0 -15
  189. package/templates/game/include/clpp/libs/pin.clh +0 -28
  190. package/templates/game/include/clpp/libs/promise.clh +0 -24
  191. package/templates/game/include/clpp/libs/roster.clh +0 -123
  192. package/templates/game/include/clpp/libs/shift.clh +0 -22
  193. package/templates/game/include/clpp/libs/spark.clh +0 -28
  194. package/templates/game/include/clpp/libs/stage.clh +0 -23
  195. package/templates/game/include/clpp/libs/sweep.clh +0 -23
  196. package/templates/game/include/clpp/libs/trace.clh +0 -18
  197. package/templates/game/include/clpp/libs/ward.clh +0 -19
  198. package/templates/game/include/clpp/libs.clh +0 -31
  199. package/templates/game/include/clpp/roblox.clh +0 -41
  200. package/templates/game/rokit.toml +0 -5
  201. package/templates/game/src/Client/Controllers/DataController.client.clpp +0 -7
  202. package/templates/game/src/Client/Main.client.clpp +0 -4
  203. package/templates/game/src/Declarations/Net.flare +0 -5
  204. package/templates/game/src/Include/GameTypes.clh +0 -40
  205. package/templates/game/src/Modules/Core/Guard.server.clpp +0 -7
  206. package/templates/game/src/Modules/Core/PlayerHandler.server.clpp +0 -24
  207. package/templates/game/src/Server/Boot/DataBoot.server.clpp +0 -13
  208. package/templates/game/src/Server/Main.server.clpp +0 -4
  209. package/templates/game/stylua.toml +0 -9
  210. package/templates/game/wally.toml +0 -12
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const https = require("node:https");
6
+
7
+ const pkg = require("../package.json");
8
+ const root = path.resolve(__dirname, "..");
9
+ const exe = process.platform === "win32" ? "cluaupp.exe" : "cluaupp";
10
+ const outDir = path.join(root, "native", "bin");
11
+ const outFile = path.join(outDir, exe);
12
+
13
+ if (process.env.CLUAUPP_INSTALL_NATIVE !== "1") {
14
+ process.exit(0);
15
+ }
16
+
17
+ if (fs.existsSync(outFile)) {
18
+ process.exit(0);
19
+ }
20
+
21
+ if (process.env.CLUAUPP_SKIP_NATIVE_DOWNLOAD === "1") {
22
+ console.log("cluaupp: native download skipped by CLUAUPP_SKIP_NATIVE_DOWNLOAD=1");
23
+ process.exit(0);
24
+ }
25
+
26
+ const version = String(pkg.version || "0.0.0");
27
+ const fileName = `cluaupp-${version}-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`;
28
+ const url = `https://github.com/KartzRbx/Cluaupp/releases/download/v${version}/${fileName}`;
29
+
30
+ fs.mkdirSync(outDir, { recursive: true });
31
+
32
+ https
33
+ .get(url, (res) => {
34
+ if (res.statusCode !== 200) {
35
+ console.warn(`cluaupp: native binary not found for ${process.platform}-${process.arch} (${res.statusCode}), fallback to Node runtime`);
36
+ res.resume();
37
+ return;
38
+ }
39
+ const file = fs.createWriteStream(outFile, { mode: 0o755 });
40
+ res.pipe(file);
41
+ file.on("finish", () => {
42
+ file.close(() => {
43
+ if (process.platform !== "win32") {
44
+ try {
45
+ fs.chmodSync(outFile, 0o755);
46
+ } catch {
47
+ // ignore chmod errors
48
+ }
49
+ }
50
+ console.log(`cluaupp: native installed at ${path.relative(root, outFile)}`);
51
+ });
52
+ });
53
+ })
54
+ .on("error", (err) => {
55
+ console.warn(`cluaupp: native download failed (${err.message}), fallback to Node runtime`);
56
+ });
package/skills/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # CL++ agent skills
2
2
 
3
- Cursor skills that teach the agent how to write CL++ and Cluaupp schemas.
3
+ Cursor skills that teach the agent how to write CL++ on the **Cluaupp Roblox target** (`.clp`, `link`, top-level scripts).
4
4
 
5
5
  `cluaupp init` copies this folder to `.cursor/skills/` in the game.
6
6
 
7
7
  | Skill | When |
8
8
  | --- | --- |
9
- | `clpp-language` | `.clpp` / `.clh` / schemas, compile, accessors |
9
+ | `clpp-language` | `.clp` / schemas, `link`, compile, accessors |
10
10
  | `clpp-style` | professional layout, named callbacks, no leftover diagnostics |
11
11
  | `clpp-hive-flare` | Hive ECS + Flare packets, server authority |
12
12
 
13
- CL++ highlighting still comes from `clpp setup`. Schema highlighting (`.hive`, `.flare`, …) comes from `cluaupp intellisense`.
13
+ Syntax highlighting: CL++ (`clp`) via the Cluaupp/CL++ extension. Schema files (`.hive`, `.flare`, …) via `cluaupp intellisense`.
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  name: clpp-hive-flare
3
- description: Design server-authoritative systems with Hive ECS and Flare packets. Use when editing .hive, .flare, CombatServer, CombatClient, hitboxes, AttackIntent, or when the user mentions Hive, Flare, ECS, snapshot, or hitbox.
3
+ description: Design server-authoritative systems with Hive ECS and Flare packets. Use when editing .hive, .flare, combat services, hitboxes, AttackIntent, or when the user mentions Hive, Flare, ECS, snapshot, or hitbox.
4
4
  ---
5
5
 
6
6
  # Hive + Flare
7
7
 
8
- Server writes Hive columns and owns gameplay. Client sends intent and plays visuals.
8
+ Server writes Hive columns and owns gameplay. Client sends intent and plays visuals. **Ward** gates inbound client buffers.
9
9
 
10
10
  ## Schema
11
11
 
12
- `.hive`:
12
+ `src/ReplicatedStorage/Shared/PlayerECS.hive`:
13
13
 
14
14
  ```
15
15
  opt name = PlayerECS
@@ -21,7 +21,7 @@ component Combo { i32 stage }
21
21
  component Alive { i32 flag }
22
22
  ```
23
23
 
24
- `.flare`:
24
+ `src/ReplicatedStorage/Shared/Net.flare`:
25
25
 
26
26
  ```
27
27
  opt name = Net
@@ -32,48 +32,52 @@ packet CombatHello(i32 entityId, i32 health) from Server
32
32
  packet HitResult(Player attacker, Player victim, i32 damage, i32 combo) from Server
33
33
  ```
34
34
 
35
- Do not edit generated `.clh`. Change the schema and rebuild.
35
+ Edit schemas, run `cluaupp build`, then `link` the generated modules — do not hand-edit `out/` Luau.
36
36
 
37
37
  ## Authority
38
38
 
39
- - One `Schema.New()` on the **server** struct.
40
- - Map `Player → entity` with `Roster` (`Roster.New()`). Do not write `new Roster()` — CL++ emits `Instance.new("Roster")` and Studio crashes.
41
- - Allocate ids with `NextEntity` (see clpp-language compiler notes).
42
- - Client never `Set`s Hive columns. Client stores replica fields from server packets.
39
+ - One `PlayerECS.New()` (or generated name) on the **server**.
40
+ - Map `Player → entity` with `Roster`.
41
+ - Allocate ids with `NextEntity` (see [compiler.md](../clpp-language/compiler.md)).
42
+ - Client never `Set`s authoritative Hive columns; mirror from server packets.
43
43
  - `Ward.Allow(player, channel, rate, burst)` on every attack remote.
44
44
 
45
45
  ## Hitbox
46
46
 
47
47
  On each accepted click:
48
48
 
49
- 1. Client `AttackIntent.FireServer()` then spawn local Part with `CanTouch = false`.
49
+ 1. Client `Net.AttackIntent.FireServer()` then spawn local Part with `CanTouch = false`.
50
50
  2. Server validates alive + cooldown + Ward, advances combo, spawns Part with `CanTouch = true`.
51
- 3. `Touched` lambda only calls `@this.OnHitboxTouched(...)`.
52
- 4. `OnHitboxTouched` resolves a player victim, dedupes with `Roster`, then `ApplyHit`.
53
- 5. `ApplyHit` writes Hive Health, assigns `humanoid.Health`, `HitResult.FireAll`.
51
+ 3. `Touched ~>` lambda only calls `@this.OnHitboxTouched(...)`.
52
+ 4. `OnHitboxTouched` resolves victim, dedupes with `Roster`, then `ApplyHit`.
53
+ 5. `ApplyHit` writes Hive Health, assigns `humanoid.Health`, `Net.HitResult.FireAll(...)`.
54
54
 
55
55
  Destroy hitboxes with `spawn { task::wait(life); hitbox.Destroy(); }`.
56
56
 
57
57
  ## Handshake
58
58
 
59
- Client `init`: construct the struct, init fields, bind input, `CombatReady.FireServer()`.
60
- Server `OnReady`: ensure fighter row, `CombatHello.Fire(player, entity, health)`.
59
+ Client boot (`*.client.clp`): `link` Net, bind input, `Net.CombatReady.FireServer()`, listen for `Net.CombatHello`.
61
60
 
62
- ## Includes
61
+ Server boot (`*.server.clp`):
63
62
 
64
- Server header may include `"ReplicatedStorage/Shared/Net/Net.clh"` and the generated Hive header.
63
+ ```clp
64
+ link @clpp.roblox;
65
+ link @ReplicatedStorage.Shared.Net as Net;
66
+ link @ReplicatedStorage.Shared.PlayerECS as PlayerECS;
65
67
 
66
- Client compiling script includes Net itself:
67
-
68
- ```clpp
69
- #include "ReplicatedStorage/Shared/Net/Net.clh"
70
- #include "../../../ReplicatedStorage/Shared/Services/Combat/CombatClient.clh"
68
+ Net.CombatReady ~> func (Player player) {
69
+ << ensure fighter row, Net.CombatHello.Fire(player, entityId, health);
70
+ };
71
71
  ```
72
72
 
73
- After `cluaupp build`, client Luau must read:
73
+ ## Links
74
74
 
75
- ```luau
76
- const Net = require(ReplicatedStorage.Shared.Net.Net)
75
+ ```clp
76
+ link @clpp.roblox;
77
+ link @ReplicatedStorage.Shared.Net as Net;
78
+ link @ReplicatedStorage.Shared.PlayerECS as PlayerECS;
79
+ link @clpp.libs.hive as Hive;
80
+ link @clpp.libs.ward as Ward;
77
81
  ```
78
82
 
79
- If it still says `script.Parent.Parent.Parent.Parent.ReplicatedStorage`, Play will error `ReplicatedStorage is not a valid member of Players`.
83
+ After `cluaupp build`, client Luau must `require` via `ReplicatedStorage` paths — not `script.Parent…Players.ReplicatedStorage`. Cluaupp postprocess rewrites bad chains; if `out/` still shows a broken path, fix the `link` and rebuild.
@@ -1,59 +1,82 @@
1
1
  ---
2
2
  name: clpp-language
3
- description: Write valid CL++ (Cluaupp) that compiles to Luau. Always rebuild and fix unused-parameter and compile errors until cluaupp build is clean. Use when editing .clpp, .clh, .clp, .hive, .flare, .mint, .bloom, .helm, .shift, or .axiom files, compiling with cluaupp/clpp, or when the user mentions CL++, Cluaupp, Hive, or Flare.
3
+ description: Write valid CL++ on the Cluaupp Roblox target (.clp, link-only, top-level scripts). Always rebuild until cluaupp build is clean. Use when editing .clp, .hive, .flare, .mint, .bloom, .helm, .shift, .axiom, compiling with cluaupp, or when the user mentions CL++, Cluaupp, Hive, or Flare.
4
4
  ---
5
5
 
6
- # CL++ language
6
+ # CL++ on Cluaupp (Roblox target)
7
7
 
8
- CL++ **0.8+** is C++-inspired source that `clpp` emits as Luau. Cluaupp orchestrates Rojo, includes, Hive, and Flare. There is no `int main()`. Scripts enter at `void init()`.
8
+ **CL++ 0.10** is the language. **Cluaupp** in this repo parses `.clp`, checks Roblox APIs, and emits Luau + Rojo. There is no `int main()` and **no `void init()`** on the Roblox target — entry scripts run **top-level** code when they load.
9
9
 
10
- Read [compiler.md](compiler.md) before using Hive `Entity` / `Has` / `Despawn`, `Humanoid.TakeDamage`, `Vector3::new`, or `namespace`.
10
+ Read [compiler.md](compiler.md) before Hive `Entity` / `Has` / `Despawn`, `Humanoid.TakeDamage`, `Vector3::new`, or legacy emit quirks.
11
11
 
12
12
  ## Files
13
13
 
14
14
  | Source | Runtime |
15
15
  | --- | --- |
16
- | `*.server.clpp` | Script |
17
- | `*.client.clpp` | LocalScript |
18
- | untagged `.clpp` / `.clp` | ModuleScript — do not put `init()` unless require should run it |
19
- | `.clh` in `src/` | types/modules; prefer `import { } from` |
20
- | `#include <clpp/...>` | IntelliSense only; emits `CluauppLibs` require |
21
- | `.flare` `.hive` `.mint` `.bloom` `.helm` `.shift` `.axiom` | schemas; do not edit the generated `.clh` |
16
+ | `*.server.clp` | Script |
17
+ | `*.client.clp` | LocalScript |
18
+ | untagged `*.clp` under `src/ReplicatedStorage/…` | ModuleScript — shared `func` and constants |
19
+ | `.flare` `.hive` `.mint` `.bloom` `.helm` `.shift` `.axiom` | schemas; edit schema, run `cluaupp build` |
22
20
 
23
- Entry scripts: `#pragma strict` then imports/includes then functions then `void init()`.
24
- Headers: `#pragma once`, structs, field defaults, method prototypes. Bodies live in `.clpp`.
21
+ Default tree: `cluaupp init` → `templates/game-modern` with `rootDir: "src"` in `cluaupp.config.json`.
25
22
 
26
- ## Accessors (law)
23
+ Legacy `.clpp` / `.clh` / `#include` / `import { } from` may still exist in old games — **do not** use them in new Roblox code.
24
+
25
+ ## Modules (`link` only)
26
+
27
+ ```clp
28
+ link @clpp.roblox;
29
+ link @clpp.libs.ward as Ward;
30
+ link @clpp.libs.keep as Keep;
31
+ link @ReplicatedStorage.Shared.CombatRules as CombatRules;
32
+ link @ReplicatedStorage.Shared.Net as Net;
33
+ ```
34
+
35
+ - `@clpp.roblox` — prelude / engine bindings
36
+ - `@clpp.libs.<name>` — CluauppLibs (`require(ReplicatedStorage.CluauppLibs.*)`)
37
+ - `@ReplicatedStorage…` / `@ServerScriptService…` — project modules (Rojo paths)
38
+
39
+ No `export` keyword — top-level declarations are the module API. Cycles → diagnostic.
40
+
41
+ Desktop-only links (`@clpp.window`, `@clpp.gfx`, `@clpp.gui`) are **rejected** on the Roblox target.
42
+
43
+ ## Script body
44
+
45
+ ```clp
46
+ link @clpp.roblox;
47
+ link @clpp.libs.sweep as Sweep;
48
+
49
+ Sweep life = Sweep.New();
50
+ Players players = GetService<Players>();
51
+
52
+ players.PlayerAdded ~> func (Player player) {
53
+ life.LinkToInstance(player.Character);
54
+ };
55
+ ```
56
+
57
+ Use `@server` / `@client` / `@parallel` on `func` when one file mixes contexts (rare — prefer separate `.server.clp` / `.client.clp`).
58
+
59
+ Comments: prefer `<<` (CL++ 0.10 parity). `//` may parse; do not teach it in new code.
60
+
61
+ ## Accessors
27
62
 
28
63
  CL++ has no `->`. Instances are `Player player`, never `Player*`.
29
64
 
30
65
  | Write | Meaning |
31
66
  | --- | --- |
32
- | `player.Name` / `player.Kick()` | property / instance method (`.` still passes self) |
33
- | `player:Kick()` | protected `pcall` form — do not use as normal method call |
34
- | `task::wait` / `Class::Method` | static, method definition, call on the struct table |
35
- | `signal~>Connect(fn)` | Sweep janitor Connect |
67
+ | `player.Name` / `player.Kick()` | property / instance method |
68
+ | `player:Kick()` | protected `pcall` — not normal calls |
69
+ | `task::wait` / `Class::Method` | static / method definition |
70
+ | `signal ~> handler` | connect (often Sweep-owned) |
36
71
  | `"hi " .: name` | concat |
37
72
  | `expr?` | Result try (not optional chaining) |
38
- | `Enum.UserInputType.MouseButton1` | enum |
39
- | `@this` / `@World` / `@janitor` | receiver / field **inside** `Class::Method` only, never in `init()` |
73
+ | `@this` / `@janitor` | receiver / field **inside** `Class::Method` only |
40
74
 
41
75
  Lambdas: `func (Player player) { }`. Not `[]() {}`.
42
76
 
43
- ## Modules
44
-
45
- ```clpp
46
- import { Wallet } from "./PlayerData.clh";
47
- import { PlayerData as Data } from "./PlayerData.clh";
48
- ```
49
-
50
- No `export` keyword — top-level is importable. Angle `#include <clpp/…>` is host only. Cycles → CLPP1001.
51
-
52
- Cluaupp host: resolves imports for Rojo/`require`, AUTH001, project graph, and incremental cache deps (`src/clpp/modules.ts`). Prefer `import` for app modules; keep `#include <clpp/libs/…>` for CluauppLibs.
53
-
54
77
  ## Option / Result
55
78
 
56
- ```clpp
79
+ ```clp
57
80
  Result<int, string> r = Ok(1);
58
81
  int n = r?;
59
82
  match (r) {
@@ -63,61 +86,31 @@ match (r) {
63
86
  optional<int> o = Some(1);
64
87
  ```
65
88
 
66
- CLPP0202 = Result→plain assign. CLPP1101 = `?` on non-Result. CLPP1102 = non-exhaustive match.
67
-
68
- ## Constructs to use
69
-
70
- ```clpp
71
- guard (player) else {
72
- return;
73
- }
74
-
75
- spawn {
76
- task::wait(0.18);
77
- hitbox.Destroy();
78
- };
79
-
80
- for (Player player in players.GetPlayers()) {
81
- @this.RegisterFighter(player);
82
- }
83
-
84
- Part hitbox = new Part(workspace);
85
- Vector3 size = Vector3(5, 6, 4);
86
- CFrame offset = CFrame(0, 0, -3.2);
87
- Color3 color = Color3(1, 0.25, 0.2);
88
- Players players = GetService<Players>();
89
- ```
89
+ ## Services
90
90
 
91
- ## Constructs that do not exist
91
+ `GetService<T>()` is **Cluaupp Roblox Target** (registry, Context Safety, `CLUAU_SVC001`) — use `link @clpp.roblox;` first. Do not write `game:GetService` in `.clp`.
92
92
 
93
- `namespace` (use `struct`), `->`, `do/while`, C++ `try/catch` (use Result/`?` or `pcall`), `goto`, `Player*`, ISO `std::`, C++ captures `[&]`, invented `export` keyword.
93
+ ## Constructs that do not exist (Roblox target)
94
94
 
95
- `wait()` as a free function is unreliable — use `task::wait` inside `spawn { }`.
96
- `delay(n, fn)` is unreliable — use `spawn { task::wait(n); ... }`.
95
+ `#include`, `import { } from`, `void init()` as entry, `.clh` headers as the module system, `namespace` (use `struct`), `->`, C++ `try/catch` (use Result/`?`), `Player*`, invented `export`.
97
96
 
98
- Reserved Intent (do not teach as shipped): `requires`, `ensures`, `effect`, `newtype`, `unique`, `move`.
97
+ `wait()` as a free function is unreliable — `task::wait` inside `spawn { }`.
99
98
 
100
99
  ## Types and init
101
100
 
102
- Prefer `auto` only for `FindFirstChild` / `FindFirstChildWhichIsA` results and Hive worlds (`auto World = PlayerECS.New()`). Method parameters and other struct fields always have a named type (`InputObject`, `Player`). Do not type fields as `HiveWorld` — that name is an IntelliSense stub and is not imported into the generated module. Initialize every field: `int coins = 0;`, never `int coins;`.
103
- `null` is Luau `nil`.
104
- `post` / `warn` / `report` → print / warn / error.
101
+ Initialize every local and field: `int coins = 0;`. Method parameters need named types (`InputObject`, not bare `auto` except documented cases). `null` is Luau `nil`. `post` / `warn` / `report` → print / warn / error.
105
102
 
106
- ## Includes
103
+ ## Flare / Hive generated API
107
104
 
108
- - Prefer `import { Name } from "./X.clh"` for language deps
109
- - Quoted path from **src root** for generated modules: `#include "ReplicatedStorage/Shared/Net/Net.clh"`
110
- - Relative quoted `.clh` next to the script: `#include "CombatServer.clh"` (legado / same-stem splice)
111
- - Never quoted-include Net/Hive generated headers from a Shared `.clh` that a LocalScript also includes — the require path follows the compiling file
112
- - Library: `#include <clpp/libs/ward.clh>` in the **compiling** `.clpp` if the runtime require must appear in that script
105
+ Edit `src/ReplicatedStorage/Shared/*.flare` or `*.hive`, then `cluaupp build`. Gameplay uses `link @ReplicatedStorage.Shared.Net as Net` (names follow schema `opt name = …`). Do not hand-edit generated `out/` Luau.
113
106
 
114
107
  ## Fix until clean
115
108
 
116
- After writing CL++, run `cluaupp build`. Unused parameters, bad includes, and type errors are blockers — change the code until the compiler is silent. Nested `func` captures do not count as uses; see [compiler.md](compiler.md).
109
+ Run `cluaupp build`. Unused parameters, bad `link`, and type errors are blockers. Nested `func` captures do not count as uses — see [compiler.md](compiler.md).
117
110
 
118
111
  ## Layout
119
112
 
120
- - Server systems: `src/ServerScriptService/Services/`
121
- - Client controllers: `src/StarterPlayer/StarterPlayerScripts/Controllers/`
122
- - Shared types/schemas: `src/ReplicatedStorage/Shared/`
123
- - If it needs `DataStoreService`, it is server. If it needs `UserInputService`, it is client.
113
+ - Server: `src/ServerScriptService/`
114
+ - Client: `src/StarterPlayer/StarterPlayerScripts/`
115
+ - Shared: `src/ReplicatedStorage/Shared/`
116
+ - DataStore / authoritative logic → server. `UserInputService` / billboards → client.
@@ -1,10 +1,10 @@
1
- # CL++ compiler workarounds
1
+ # Cluaupp compiler workarounds
2
2
 
3
- These are emit bugs, not style. Prefer the workaround until `clpp` generates a colon call.
3
+ These are emit/checker quirks, not style. Prefer the workaround until the compiler fixes the root cause.
4
4
 
5
5
  ## Hive
6
6
 
7
- `World.Entity()`, `World.Has(...)`, `World.Despawn(...)` often emit `.Entity()` / `.Has()` / `.Despawn()` (no self).
7
+ `World.Entity()`, `World.Has(...)`, `World.Despawn(...)` may emit without `self`.
8
8
 
9
9
  | Need | Write |
10
10
  | --- | --- |
@@ -12,73 +12,61 @@ These are emit bugs, not style. Prefer the workaround until `clpp` generates a c
12
12
  | membership | `auto value = @World.Get(entity, Comp); if (!value) return;` |
13
13
  | despawn | `@World.Remove(entity, Comp);` per component |
14
14
 
15
- `PlayerECS.New()` is authoritative. Only the server writes columns. Client worlds do not spawn rows.
15
+ `PlayerECS.New()` is authoritative on the server. Client worlds do not spawn authoritative rows.
16
16
 
17
- Generated `PlayerECS.clh` may contain `namespace PlayerECS`. Do not copy that into hand-written `.clh`. Use the generated names as `PlayerECS.Health`.
17
+ Use generated schema types (`PlayerECS.Health`) from `link @ReplicatedStorage.Shared.PlayerECS as PlayerECS;` — do not invent a `HiveWorld` field type unless the checker already knows it.
18
18
 
19
19
  ## Roblox instances
20
20
 
21
- `humanoid.TakeDamage(n)` may emit without colon. Write `humanoid.Health = currentHealth;`.
21
+ `humanoid.TakeDamage(n)` may emit without colon. Prefer `humanoid.Health = currentHealth;`.
22
22
 
23
- `Vector3::new(x, y, z)` fails semantic check. Write `Vector3(x, y, z)`. Same for `CFrame(...)` and `Color3(...)`.
23
+ `Vector3::new(x, y, z)` may fail semantic check. Write `Vector3(x, y, z)`. Same for `CFrame(...)` and `Color3(...)`.
24
24
 
25
- Player-local hitbox offset is CFrame multiply, not LookVector math and not `ToWorldSpace` in source:
25
+ Player-local hitbox offset:
26
26
 
27
- ```clpp
27
+ ```clp
28
28
  return rootPart.CFrame * CFrame(0, 0, @HITBOX_FORWARD);
29
29
  ```
30
30
 
31
- Native CL++ still emits `.ToWorldSpace(` without colon (`self` becomes the offset at world origin). Cluaupp postprocess rewrites that to `:ToWorldSpace(`. Prefer `*` in source.
32
-
33
31
  Cluaupp reindents emitted Luau (tabs). Do not hand-fix `out/` indent.
34
32
 
35
- `~>` Connect: Cluaupp hoists the method Sweep to `self.janitor` (one per controller). Hitbox/player binds `LinkToInstance` so they die with that instance. Do not add a second `new Sweep()` next to `~>`.
33
+ `~>` Connect: Cluaupp hoists the method Sweep to `self.janitor` where applicable. Instance binds should `LinkToInstance` so they die with that instance.
36
34
 
37
35
  ## Flare
38
36
 
39
- `FireAll` on generated packets is a function on the packet table (`api.FireAll`), so `.FireAll(...)` is correct.
40
-
41
- `Fire` / `FireServer` take self — `.Fire(player, ...)` is the CL++ instance-method form.
42
-
43
- Connect packets with Sweep: `Net.AttackIntent~>Connect(func (Player player) { @this.OnAttack(player); });`
37
+ Generated packets: `Net.Hit.FireServer(...)`, server `Net.Hit ~> func (Player player, …) { }`, queries `Net.GetCoins.On` / `Net.GetCoins.Invoke()`.
44
38
 
45
- `clpp` emits `require(script.Parent.Parent...ReplicatedStorage.Shared.Net.Net)`. Under `PlayerScripts` that path is `Players.ReplicatedStorage` and crashes. Cluaupp postprocess rewrites those requires to `require(ReplicatedStorage.Shared...)`. After a build, client files must show `game:GetService("ReplicatedStorage")`, never a `script.Parent` chain into `ReplicatedStorage`.
39
+ `clpp` legacy emit may use `script.Parent…ReplicatedStorage` requires. Cluaupp postprocess rewrites to `ReplicatedStorage` paths. After build, client `out/` must not walk into `Players.ReplicatedStorage`.
46
40
 
47
- Do not put `table.pack(...)` inside a nested `function()` in Flare — `...` is only valid in the vararg function. Pack first, then `pcall`.
41
+ Do not put `table.pack(...)` inside a nested `function()` in generated Flare glue — `...` is only valid in the vararg function.
48
42
 
49
43
  ## Callbacks
50
44
 
51
- Keep `func (...) { }` as a one-line dispatch to a named `Class::Method`. Business logic belongs in the method so `@this` and fields work.
45
+ Keep `func (...) { }` as a one-line dispatch to a named `Class::Method` or top-level `func`. Business logic belongs there so `@this` and fields work.
52
46
 
53
- Call other methods with a dot on the receiver. `@Name(...)` emits `pcall` (`self:Name`) and hides errors.
54
-
55
- ```clpp
56
- hitbox.Touched~>Connect(func (BasePart hitPart) {
47
+ ```clp
48
+ hitbox.Touched ~> func (BasePart hitPart) {
57
49
  @this.OnHitboxTouched(hitPart, attacker, attackerCharacter, attackerEntity, struckPlayers);
58
- });
50
+ };
59
51
  ```
60
52
 
61
- ## Struct export types
62
-
63
- `auto` on a method parameter emits a nameless type (`input,` with no annotation). Use a real type: `InputObject input`, never `auto input`.
64
-
65
- `const void Method();` emits `(self: T),` — invalid Luau, missing `-> ()`. Declare procedures as `const bool Method();`, `return false` on guard failure, `return true` at the end.
53
+ ## Struct / export types
66
54
 
67
- Uninitialized fields emit `nil` in the constructor. Write `int ComboStage = 0;`, never `int ComboStage;`.
55
+ `auto` on a method parameter may emit a nameless type. Use `InputObject input`, not `auto input`.
68
56
 
69
- `auto World` emits `World: any`. Do **not** type the field as `HiveWorld` — that name is only an IntelliSense stub in `hive.clh`. It is not imported into the generated module.
57
+ Uninitialized fields emit `nil` in constructors. Write `int ComboStage = 0;`.
70
58
 
71
- Construct with `Roster.New()`. Do not write `new Roster()` — CL++ emits `Instance.new("Roster")`, which is not a Roblox class. Cluaupp also rewrites leftover `Instance.new("Roster")` to `Roster.new()`.
59
+ Construct with `Roster.New()` / `Sweep.New()` — not `Instance.new("Roster")`. Cluaupp rewrites common mistakes in postprocess.
72
60
 
73
61
  ## Unused parameters
74
62
 
75
- A name used only inside `func () { }` is unused. The compiler still flags it. Bind it in the outer `guard` (or assign it to a field) so the diagnostic disappears. Do not ignore unused errors.
63
+ A name used only inside `func () { }` is unused. Bind it in the outer `guard` (or assign to a field) so the diagnostic clears.
76
64
 
77
65
  ## Multiline return
78
66
 
79
67
  Do not write `return (` across lines. Split into locals:
80
68
 
81
- ```clpp
69
+ ```clp
82
70
  bool isMouse = input.UserInputType == Enum.UserInputType.MouseButton1;
83
71
  bool isTouch = input.UserInputType == Enum.UserInputType.Touch;
84
72
  return isMouse || isTouch;
@@ -86,4 +74,4 @@ return isMouse || isTouch;
86
74
 
87
75
  ## Verify
88
76
 
89
- After every edit run `cluaupp build`. If it fails, fix the source and build again. Do not leave unused-parameter, type, or include errors visible. Open the matching `out/**/*.luau` and confirm `require` paths and `:` method calls.
77
+ After every edit run `cluaupp build`. Open matching `out/**/*.luau` and confirm `require` paths and `:` method calls.
@@ -1,32 +1,32 @@
1
1
  ---
2
2
  name: clpp-style
3
- description: Write professional CL++ with small named functions, semantic identifiers, header/script split, and named callbacks. Always fix compiler diagnostics (unused parameters, types) instead of leaving them on screen. Use when refactoring .clpp/.clh, organizing combat or services, extracting lambdas, or when the user asks for código profissional, boa conduta, nomenclatura, or organização.
3
+ description: Write professional CL++ with small named functions, semantic identifiers, top-level boot scripts, and named callbacks. Always fix compiler diagnostics instead of leaving them on screen. Use when refactoring .clp, organizing combat or services, extracting lambdas, or when the user asks for código profissional, boa conduta, nomenclatura, or organização.
4
4
  ---
5
5
 
6
- # CL++ professional style
6
+ # CL++ professional style (Roblox target)
7
7
 
8
- Apply this whenever writing or refactoring CL++.
8
+ Apply whenever writing or refactoring `.clp` for Cluaupp.
9
9
 
10
10
  ## Conduct
11
11
 
12
12
  1. Initialize everything. `int comboStage = 0;`, never an uninitialized local.
13
13
  2. Small functions. One behavior, named after the behavior.
14
- 3. No magic numbers. `const float HITBOX_LIFE = 0.18;` on the struct.
14
+ 3. No magic numbers. `const float HITBOX_LIFE = 0.18;` next to the struct or file scope.
15
15
  4. Early return. `guard (cond) else { return; }` — no nested pyramids.
16
- 5. Headers declare, scripts define. Prototypes in `.clh`, bodies in `.clpp`.
17
- 6. Do not share mutable statics across server and client. Net or Keep, never a shared writeable singleton.
18
- 7. Procedures are `const bool`, never `const void` — void emits a broken Luau function type. Parameters always have a named type (`InputObject`, not `auto`).
16
+ 5. **One concern per file.** Shared APIs live in untagged `src/ReplicatedStorage/…/*.clp`; boot and wiring live in `*.server.clp` / `*.client.clp` with top-level statements (no `void init()`).
17
+ 6. Do not share mutable statics across server and client. Net, Keep, or Flare — never a shared writeable singleton.
18
+ 7. Procedures return `bool` when you need a Luau-callable shape; parameters always have a named type (`InputObject`, not `auto`).
19
19
 
20
20
  ## Callbacks
21
21
 
22
- Never put combat/network logic inside `func () { }`.
22
+ Never put combat/network logic inside anonymous `func () { }` bodies.
23
23
 
24
- The lambda only forwards to a named method. Call methods as `@this.Name(...)` (dot). `@Name(...)` emits a `pcall` and swallows errors.
24
+ The lambda only forwards to a named function or method. Call methods as `@this.Name(...)` (dot). `@Name(...)` emits a `pcall` and swallows errors.
25
25
 
26
- ```clpp
27
- hitbox.Touched~>Connect(func (BasePart hitPart) {
26
+ ```clp
27
+ hitbox.Touched ~> func (BasePart hitPart) {
28
28
  @this.OnHitboxTouched(hitPart, attacker, attackerCharacter, attackerEntity, struckPlayers);
29
- });
29
+ };
30
30
  ```
31
31
 
32
32
  Name event handlers `On` + event: `OnAttack`, `OnHitboxTouched`, `OnCharacterSpawned`, `OnReady`.
@@ -41,55 +41,42 @@ Name factories `Create` / `Spawn` / `Resolve` / `Try`.
41
41
  | method | PascalCase verb | `ResolveVictim`, `AdvanceCombo` |
42
42
  | local / param | camelCase, role-first | `attackerEntity`, `hitPart`, `struckPlayers` |
43
43
  | constant | SCREAMING_SNAKE | `ATTACK_INTERVAL`, `MAX_HEALTH` |
44
- | player refs | role | `attacker`, `victim`, `player` — not `p`, `plr`, `currentPlayer` unless needed |
44
+ | player refs | role | `attacker`, `victim`, `player` |
45
45
  | Hive ids | `*Entity` | `fighterEntity`, `victimEntity` |
46
46
 
47
- Do not abbreviate (`hp` → `currentHealth`, `box` → `hitbox`, `gp` → `gameProcessed`).
47
+ Do not abbreviate (`hp` → `currentHealth`, `box` → `hitbox`).
48
48
 
49
- ## Header layout
49
+ ## Module layout
50
50
 
51
- Group prototypes on the struct in this order:
51
+ Group shared `func` and constants in ReplicatedStorage modules in this order when it helps readers:
52
52
 
53
- 1. Session bind / lifecycle
53
+ 1. Constants / types
54
54
  2. Queries (`IsFighterAlive`, `CanAcceptAttack`)
55
55
  3. World writes (`SeedFighter`, `AdvanceCombo`)
56
- 4. Hitbox
57
- 5. Damage / replication
56
+ 4. Hitbox / damage helpers
58
57
 
59
- Keep constants next to the fields they configure.
58
+ Server `.server.clp` files: top-level `link`, then binders (`Ward.Start()`, `Net.Hit ~> …`, `Players.PlayerAdded ~>`).
60
59
 
61
- ## Script layout
60
+ ## Links in a compiling script
62
61
 
63
- Define methods in the same order as the header. `void init()` only calls binders:
64
-
65
- ```clpp
66
- void init() {
67
- CombatServer::BindPlayerSessions();
68
- CombatServer::BindCombatRemotes();
69
- }
62
+ ```clp
63
+ link @clpp.roblox;
64
+ link @clpp.libs.ward as Ward;
65
+ link @clpp.libs.sweep as Sweep;
66
+ link @ReplicatedStorage.Shared.CombatRules as CombatRules;
67
+ link @ReplicatedStorage.Shared.Net as Net;
70
68
  ```
71
69
 
72
- ## Includes in a compiling script
73
-
74
- ```clpp
75
- #pragma strict
76
- #include <clpp/roblox.clh>
77
- #include <clpp/libs/ward.clh>
78
- #include "CombatServer.clh"
79
- ```
80
-
81
- Angled library includes that must emit a `require` belong in the `.clpp`, not only the `.clh`.
70
+ Library `link @clpp.libs.*` must appear in the script that needs the runtime `require`.
82
71
 
83
72
  ## Comments
84
73
 
85
- No narration. A name should replace a comment. If a workaround exists, one line pointing at the compiler limitation is enough.
74
+ No narration. Prefer `<<` for non-obvious notes. One line for compiler limitations is enough.
86
75
 
87
76
  ## Never leave errors
88
77
 
89
- Diagnostics are work, not a report. Do not stop, explain, or ask while the file still shows errors. Fix, rebuild, fix again until `cluaupp build` exits 0 and the compiling `.clpp` has no unused-parameter / type diagnostics.
90
-
91
- CL++ does **not** count uses inside a nested `func () { }` as uses of the outer parameters. Mention every parameter in the method body (`guard`) before the lambda.
78
+ Fix until `cluaupp build` exits 0. CL++ does **not** count uses inside nested `func () { }` as uses of outer parameters — mention them in the outer `guard` before the lambda.
92
79
 
93
- Flare handlers must match the packet arity. If a field is unused, put it in the `guard` — do not drop it from the signature.
80
+ Flare handlers must match packet arity. Unused fields go in `guard`, not dropped from the signature.
94
81
 
95
- Truth is `cluaupp build`, not clangd / C++ IntelliSense on `.clpp`. If the editor squiggles but the compiler is clean, ignore the squiggle. If the compiler errors, change the code.
82
+ Truth is `cluaupp build`, not C++ IntelliSense on `.clp`. If the compiler is clean, ship it.
@@ -132,7 +132,7 @@ export function writeProfileCache(profile: RobloxTargetProfile, outPath?: string
132
132
  export function profileContentHash(profile: RobloxTargetProfile): string {
133
133
  const clone = { ...profile, sources: { ...profile.sources } };
134
134
  for (const key of Object.keys(clone.sources)) {
135
- clone.sources[key] = { ...clone.sources[key], loadedAt: "" };
135
+ clone.sources[key] = { ...clone.sources[key], loadedAt: "", path: "" };
136
136
  }
137
137
  return hashBuffer(JSON.stringify(clone));
138
138
  }
package/src/api/loader.ts CHANGED
@@ -21,7 +21,7 @@ export function loadJsonFile<T>(id: string, filePath: string): LoadedSource<T> {
21
21
  meta: {
22
22
  id,
23
23
  path: absolute,
24
- hash: hashBuffer(raw),
24
+ hash: hashBuffer(text.replace(/\r\n/g, "\n")),
25
25
  loadedAt: new Date().toISOString(),
26
26
  version: typeof (data as { Version?: unknown }).Version !== "undefined"
27
27
  ? (data as { Version: string | number }).Version
@@ -54,7 +54,7 @@ export function overridesHash(): string {
54
54
  if (!name.endsWith(".json")) {
55
55
  continue;
56
56
  }
57
- parts.push(name, fs.readFileSync(path.join(dir, name), "utf8"));
57
+ parts.push(name, fs.readFileSync(path.join(dir, name), "utf8").replace(/\r\n/g, "\n"));
58
58
  }
59
59
  return hashBuffer(parts.join("\n"));
60
60
  }