cluaupp 0.1.2 → 0.1.5

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 (69) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +10 -13
  3. package/docs/README.md +13 -10
  4. package/docs/architecture.md +30 -73
  5. package/docs/cli.md +5 -6
  6. package/docs/comparison.md +3 -3
  7. package/docs/config.md +6 -6
  8. package/docs/cpp-advanced.md +10 -6
  9. package/docs/cpp-organization.md +4 -2
  10. package/docs/cpp-safety.md +11 -7
  11. package/docs/cpp-types.md +1 -1
  12. package/docs/examples/_category_.json +5 -0
  13. package/docs/examples/combat.md +239 -0
  14. package/docs/examples/data-boot.md +98 -0
  15. package/docs/examples/hud.md +96 -0
  16. package/docs/examples/index.md +43 -0
  17. package/docs/examples/leaderstats.md +140 -0
  18. package/docs/examples/shop.md +122 -0
  19. package/docs/examples/sword.md +108 -0
  20. package/docs/getting-started.md +14 -7
  21. package/docs/intellisense.md +31 -0
  22. package/docs/intro.md +3 -3
  23. package/docs/libraries/_category_.json +5 -0
  24. package/docs/libraries/dataservice.md +104 -0
  25. package/docs/libraries/index.md +22 -0
  26. package/docs/libraries/janitor.md +65 -0
  27. package/docs/libraries/more.md +79 -0
  28. package/docs/libraries/net.md +35 -0
  29. package/docs/libraries/promise.md +27 -0
  30. package/docs/oop/_category_.json +5 -0
  31. package/docs/oop/file-tags.md +48 -0
  32. package/docs/oop/index.md +22 -0
  33. package/docs/oop/modules.md +88 -0
  34. package/docs/oop/services.md +76 -0
  35. package/docs/print-cout.md +91 -0
  36. package/docs/syntax.md +63 -8
  37. package/editors/vscode/extension.js +146 -0
  38. package/editors/vscode/package.json +25 -0
  39. package/include/cluaupp/libs/janitor.hpp +7 -3
  40. package/include/cluaupp/roblox.hpp +19 -0
  41. package/package.json +66 -65
  42. package/runtime/Janitor/init.luau +4 -34
  43. package/src/architecture.js +174 -66
  44. package/src/cli.js +88 -21
  45. package/src/client/init.client.cpp +5 -0
  46. package/src/compile.js +77 -7
  47. package/src/editor-install.js +218 -0
  48. package/src/emit.js +321 -9
  49. package/src/headers.js +234 -0
  50. package/src/intellisense.js +1368 -0
  51. package/src/layout.js +129 -0
  52. package/src/lex.js +17 -9
  53. package/src/libs.js +165 -18
  54. package/src/lsp.js +227 -0
  55. package/src/parse.js +187 -6
  56. package/src/preprocess.js +118 -3
  57. package/src/server/leaderstats.server.cpp +28 -0
  58. package/src/shared/config.cpp +5 -0
  59. package/src/shared/config.h +3 -0
  60. package/src/understand.js +66 -6
  61. package/templates/game/.clangd +11 -0
  62. package/templates/game/.vscode/c_cpp_properties.json +6 -2
  63. package/templates/game/.vscode/extensions.json +6 -0
  64. package/templates/game/.vscode/settings.json +16 -2
  65. package/templates/game/cluaupp.config.json +2 -2
  66. package/templates/game/compile_flags.txt +2 -0
  67. package/templates/game/src/client/init.client.cpp +1 -0
  68. package/templates/game/src/server/leaderstats.server.cpp +1 -0
  69. package/docs/libraries.md +0 -80
package/CHANGELOG.md CHANGED
@@ -1,10 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.5
4
+
5
+ - Default emit is one tagged `.cpp` → one `.server.luau` / `.client.luau`. `"architecture": true` keeps the old ForeverHD service folders.
6
+ - `--!strict` is opt-in: `#pragma strict`, `#pragma nstrict`, or `"strict": true` in config (default `false`).
7
+ - `.h` / `.hpp` emit type ModuleScripts (`export type` + typed table). A sibling `.cpp` becomes `*Impl.luau`; the header binds those functions.
8
+ - Shared `#include` modules `require` game-rooted paths (`ReplicatedStorage.Cluaupp...` / `ServerScriptService.Cluaupp...`).
9
+
10
+ ## 0.1.4
11
+
12
+ - Quoted `#include "Header.h"` of project files becomes `const Header = require(...)`. Header-only structs emit a constructor (`TemplateData()`); const headers bind `PLAYER_DATA_VERSION` from the module. Boot scripts require services (`LeaderstatsServer:init()`).
13
+ - Keep `const` for injected `require` / `GetService` and `const function` for C++ functions (not `local`).
14
+ - `init.meta.json` stays pure JSON. Library `require` injection no longer prepends Luau onto Rojo meta files (which made `rojo serve` fail with a JSONC parse error).
15
+ - Server services emit `init.server.luau` + `init.meta.json` with **only** `RunContext.Server`. Rojo forbids `className` when an `init.*` script exists (the folder is already a Script, not a Folder). `init.luau` is pruned so the instance is not a ModuleScript.
16
+
17
+ ## 0.1.3
18
+
19
+ - Architecture: generated services keep a fixed declaration order (requires, types, constants, variables, functions, cleanup, return) without section banners. Domain `Stop` runs `janitor:Cleanup()`.
20
+ - IntelliSense: `cluaupp init` / `cluaupp intellisense` install Microsoft `ms-vscode.cpptools` (VSIX on Cursor, where the marketplace omits it), write `.vscode/c_cpp_properties.json` (LLVM clang++, C++20, `include/` + `src/`, `compile_commands.json`), and disable clangd so the two engines do not fight. `build`/`watch` only refresh `compile_commands.json`.
21
+ - `Class::method` on game types becomes `Class:method()` (`self`). Datatype/library statics stay dotted (`CFrame.lookAt`, `Color3.fromRGB`, `FormatNumber.Abbreviate`).
22
+ - `switch` / `case` / `default` / `break` compile to a one-shot `repeat` with `if` / `elseif` / `else`. The discriminant is evaluated once; stacked `case` labels share a body; `break` leaves the switch even from inside an `if`.
23
+ - Janitor typed border re-exports `_impl` (`export type Janitor = Impl.Janitor; return Impl`). It no longer invents `Has` or requires Promise for a parallel type that did not match howmanysmall.
24
+ - Emit: injected `require` / `GetService` are `const`. C++ functions emit as `const function` instead of `local function`.
25
+ - `.server.cpp` emits `init.luau` + `init.meta.json` with `RunContext.Server`. `init.server.luau` is Legacy and is pruned.
26
+ - `cout << ... << endl` emits `print(...)`. `cerr <<` emits `warn`. `cout::print` / `cout::warn` / `cout::error` / `cout::ping` map to the Roblox globals.
27
+ - Docs: [print and cout](docs/print-cout.md); [Libraries](docs/libraries/index.md) how-tos (DataService Init, Janitor, Promise, Net); [OOP structure](docs/oop/index.md) (file tags, services, modules); [Examples](docs/examples/index.md) (leaderstats, combat validation, shop, HUD, sword). GitHub Pages Learn tabs: OOP, Libraries, print/cout, Examples — generated into `site/` (`guide/oop.html`, `guide/examples.html`).
28
+
3
29
  ## 0.1.2
4
30
 
5
31
  - Watch does not write `out/` while any file fails to compile (Studio keeps the last good scripts).
6
32
  - Watch/build skip rewriting Luau whose contents did not change (a space in C++ no longer floods Rojo).
7
- - `libs/` is fill-only: missing files are restored, existing files are never overwritten or deleted. Fixes Rojo 7 crashing on `libs/ArrayIndexer` when watch/build raced a live serve.
33
+ - Watch never copies `libs/` or headers. Changing a constant no longer makes Rojo 7 crash on `libs/ArrayIndexer`.
34
+ - `libs/` on `cluaupp build` is fill-only: missing files are restored, existing files are never overwritten or deleted.
35
+ - Filename tags: `.server.cpp` → Script (`init.server.luau`), `.client.cpp` → LocalScript (`init.client.luau`), `.plugin.cpp` → Plugin, `.legacy` / `.legacy.client` / `.legacy.server` → Legacy. Bare `init.luau` is not used for `.server` (Rojo would make a ModuleScript).
8
36
  - Dropped `$optional` from `default.project.json` (Rojo 7.7 failed to deserialize it).
9
37
 
10
38
  ## 0.1.1
package/README.md CHANGED
@@ -8,18 +8,11 @@
8
8
 
9
9
  [Docs](https://kartzrbx.github.io/Cluaupp/) · [Learn](https://kartzrbx.github.io/Cluaupp/learn/) · [API](https://kartzrbx.github.io/Cluaupp/api/classes/)
10
10
 
11
- The cinematic docs site deploys to [Vercel](https://vercel.com) from `site/` (`vercel.json`). Code blocks use **Dark Modern**, **Tokyo Night**, and **Dracula**. Ask Cluaupp (AI Gateway) is the floating chat on the Vercel deploy.
12
-
13
- ```bash
14
- cp .env.example .env.local # set AI_GATEWAY_API_KEY
15
- npx vercel
16
- ```
17
-
18
11
  [![npm version](https://img.shields.io/npm/v/cluaupp.svg)](https://www.npmjs.com/package/cluaupp)
19
12
  [![Node.js](https://img.shields.io/node/v/cluaupp.svg)](https://nodejs.org)
20
13
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
21
14
 
22
- Source-to-source transpiler: you write a C++ subset, Cluaupp emits modern [Luau](https://luau.org/getting-started) (`--!strict`, `local`, `const`). C++ structure, Luau quality, one language.
15
+ Source-to-source transpiler: you write a C++ subset, Cluaupp emits modern [Luau](https://luau.org/getting-started) (`local`, `const`, optional `--!strict`). C++ structure, Luau quality, one language.
23
16
 
24
17
  No WASM. No Emscripten. No `lua_call`. Roblox APIs come out as they do in Studio: `game:GetService("Players")`, `player:FindFirstChild("leaderstats")`, `players:GetPlayers()`.
25
18
 
@@ -73,12 +66,12 @@ rojo serve
73
66
  Connect the Rojo plugin in Roblox Studio. Edit `src/**/*.{cpp,h,hpp}`, run `cluaupp watch` to rebuild on save.
74
67
 
75
68
  ```
76
- src/server/*.server.cpp → out/server/LeaderStats/ Script + ModuleScripts
77
- src/client/*.client.cpp → out/client/*.client.luau LocalScript (or a service folder)
78
- src/shared/config.* → out/shared/Config.luau typed config module
69
+ src/server/*.server.cpp → out/server/*.server.luau Script
70
+ src/client/*.client.cpp → out/client/*.client.luau LocalScript
71
+ src/shared/*.cpp → out/shared/*.luau ModuleScript
79
72
  ```
80
73
 
81
- A tiny `leaderstats.server.cpp` becomes `Main` / `PlayersManager` / `CacheController`. A combat `.server.cpp` becomes `CombatController` with your `TakeDamage` logic. Filename tags: `.server.cpp`, `.client.cpp`, `.legacy.server.cpp`, `.legacy.client.cpp`, or no tag (ModuleScript). See [Architecture](docs/architecture.md).
74
+ Filename tags: `.server.cpp`, `.client.cpp`, `.legacy.server.cpp`, `.legacy.client.cpp`, or no tag (ModuleScript). One source file becomes one instance. Set `"architecture": true` only for the old PascalCase folder split. See [Architecture](docs/architecture.md) and [OOP structure](docs/oop/index.md).
82
75
 
83
76
  ## Documentation
84
77
 
@@ -89,8 +82,12 @@ A tiny `leaderstats.server.cpp` becomes `Main` / `PlayersManager` / `CacheContro
89
82
  | [Learn](https://kartzrbx.github.io/Cluaupp/learn/) | C++ subset, Luau output, safety, architecture |
90
83
  | [CLI](docs/cli.md) | `init`, `build`, `watch`, flags |
91
84
  | [Syntax](docs/syntax.md) | C++ subset → Luau (`local`, `const`, types) |
85
+ | [print and cout](docs/print-cout.md) | `cout <<`, `cout::warn`, `endl` |
92
86
  | [Roblox API](docs/roblox-api.md) | Vector3, CFrame, UDim2, GetService, Instance.new |
93
- | [Architecture](docs/architecture.md) | PascalCase services, Types modules, not a 200-line dump |
87
+ | [Architecture](docs/architecture.md) | One file in, one file out; opt-in ForeverHD folders |
88
+ | [OOP structure](docs/oop/index.md) | File tags, services, modules, structs |
89
+ | [Libraries](docs/libraries/index.md) | DataService Init, Janitor, Promise, Net |
90
+ | [Examples](docs/examples/index.md) | Leaderstats, combat validation, shop, HUD, sword |
94
91
  | [C++ types](docs/cpp-types.md) | Typing, `const`, safety, organization |
95
92
  | [Comparison](docs/comparison.md) | vs roblox-ts and WASM toolchains |
96
93
  | [Contributing](CONTRIBUTING.md) | Tests, layout, how to ship |
package/docs/README.md CHANGED
@@ -4,16 +4,19 @@
4
4
  2. [Getting started](getting-started.md) — npm, Rojo, Wally
5
5
  3. [CLI](cli.md) — `init`, `build`, `watch`
6
6
  4. [Syntax](syntax.md) — C++ subset, `local`, `const`
7
- 5. [C++ types](cpp-types.md) — primitives, Instances, `nullptr`
8
- 6. [const](cpp-const.md) — immutability
9
- 7. [Safety](cpp-safety.md) — client trust, Janitor, Net, DataService
10
- 8. [Organization](cpp-organization.md) — server / client / shared
11
- 9. [Advanced](cpp-advanced.md) — `::` vs `:`, Wally, performance
12
- 10. [Architecture](architecture.md) — PascalCase services, Types modules, vs roblox-ts dumps
13
- 11. [Libraries](libraries.md) — Janitor, Promise, Net, Module3D, Twinkle, DataServiceV2
14
- 12. [Roblox API](roblox-api.md) — Vector3, CFrame, UDim2, classes
15
- 13. [Config](config.md) — `cluaupp.config.json`
16
- 14. [Comparison](comparison.md) — roblox-ts and WASM
7
+ 5. [print and cout](print-cout.md) — `cout <<`, `cout::warn`, `endl`
8
+ 6. [C++ types](cpp-types.md) — primitives, Instances, `nullptr`
9
+ 7. [const](cpp-const.md) — immutability
10
+ 8. [Safety](cpp-safety.md) — client trust, Janitor, Net, DataService
11
+ 9. [Organization](cpp-organization.md) — server / client / shared
12
+ 10. [Advanced](cpp-advanced.md) — `::` vs `:`, Wally, performance
13
+ 11. [Architecture](architecture.md) — one file in, one file out; opt-in ForeverHD folders
14
+ 12. [OOP structure](oop/index.md) — file tags, services, modules, structs
15
+ 13. [Libraries](libraries/index.md) — DataService Init, Janitor, Promise, Net, more
16
+ 14. [Examples](examples/index.md) — leaderstats, combat validation, shop, HUD, sword
17
+ 15. [Roblox API](roblox-api.md) — Vector3, CFrame, UDim2, classes
18
+ 16. [Config](config.md) — `cluaupp.config.json`
19
+ 17. [Comparison](comparison.md) — roblox-ts and WASM
17
20
 
18
21
  Moonwave site (local): `npx moonwave dev`
19
22
 
@@ -3,51 +3,52 @@ title: Architecture
3
3
  sidebar_position: 15
4
4
  ---
5
5
 
6
- # Output treated as a Roblox system
6
+ # One file in, one file out
7
7
 
8
- roblox-ts decides **what instance you get** from a filename **key** (the same idea as Rojo):
8
+ roblox-ts decides **what instance you get** from a filename **key** (the same idea as Rojo). Cluaupp does the same — and **stops there** by default. It does not invent Main / Controller / Types folders.
9
9
 
10
- | Key | Rojo instance |
11
- | --- | --- |
12
- | `*.server.ts` | Script |
13
- | `*.client.ts` | LocalScript |
14
- | no suffix | ModuleScript |
10
+ | Key | Rojo instance | Default output |
11
+ | --- | --- | --- |
12
+ | `*.server.cpp` | Script | `*.server.luau` |
13
+ | `*.client.cpp` | LocalScript | `*.client.luau` |
14
+ | no suffix | ModuleScript | `Name.luau` |
15
+ | `*.legacy.server.cpp` | Legacy Script | `*.server.luau` |
15
16
 
16
- Flamework then stamps a second key (`@Service` / `@Controller`) so the runtime knows the **role**. Cluaupp does both steps without decorators.
17
+ `DataBoot.client.cpp` becomes `out/client/boot/DataBoot.client.luau` with your `init()` at the end. Shared `#include` modules use `require(ReplicatedStorage.Cluaupp...)`.
17
18
 
18
- 1. **Tag** (filename) where the code runs and whether it is a Script, LocalScript, ModuleScript, or a 1:1 “legacy” dump.
19
- 2. **Intent** (AST) — what the code *is for*: players, cache, combat, input, UI, net, data, … scored from APIs and identifiers, the same idea as intent classification in program analysis (features from the tree, not a 200-line dump).
19
+ `--!strict` is opt-in: put `#pragma strict` in the `.cpp`, or set `"strict": true` in `cluaupp.config.json`.
20
20
 
21
- Leaderstats was the example. A combat `.server.cpp` is a different system and gets Combat folders, not a fake CacheController.
21
+ The ForeverHD-style folder split (`LeaderStats/Main.luau`, …) is **opt-in**: `"architecture": true`.
22
22
 
23
23
  ## File tags
24
24
 
25
25
  | Source | Meaning | Output |
26
26
  | --- | --- | --- |
27
- | `combat.server.cpp` | Server **system** | `Combat/` Script: `init.server.luau` + Main / Controllers / Types |
28
- | `hud.client.cpp` | Client **system** | `Hud/` LocalScript folder |
29
- | `boot.legacy.server.cpp` | Server script, no split | `boot.server.luau` (Rojo Script, `init()` still runs) |
30
- | `boot.legacy.client.cpp` | Client script, no split | `boot.client.luau` |
31
- | `damage.cpp` (no tag) | **Module** | `Damage.luau` ModuleScript `return { ... }` — does not auto-run |
27
+ | `combat.server.cpp` | **Script** | `combat.server.luau` |
28
+ | `hud.client.cpp` | **LocalScript** | `hud.client.luau` |
29
+ | `tools.plugin.cpp` | **Script** RunContext Plugin | `tools.luau` (legacy plugin tag) |
30
+ | `boot.legacy.server.cpp` | Legacy Script | `boot.server.luau` |
31
+ | `damage.cpp` (no tag) | **ModuleScript** | `Damage.luau` |
32
+
33
+ ## What a tagged file becomes
34
+
35
+ ```
36
+ src/server/leaderstats.server.cpp → out/server/leaderstats.server.luau
37
+ src/client/boot/DataBoot.client.cpp → out/client/boot/DataBoot.client.luau
38
+ src/shared/damage.cpp → out/shared/Damage.luau
39
+ ```
32
40
 
33
- Trivial entry files (`init.client.cpp` that only `print`) stay a single LocalScript. The planner does not invent Managers for a hello-world.
41
+ Scripts and LocalScripts keep your functions and call `init()` at the end. ModuleScripts return a table. There is no invented Main, Controller, or Types file.
34
42
 
35
- ## How the planner reasons
43
+ ## Opt-in: ForeverHD folders (`"architecture": true`)
44
+
45
+ Set `"architecture": true` in `cluaupp.config.json` to restore the old planner: PascalCase service folders, `Main` / Managers / Controllers / Types, and `require(script.Main):Start()`.
36
46
 
37
47
  ```
38
48
  filename key → server | client | module | legacy
39
49
  AST features → GetService, Instance.new, methods, identifiers
40
50
  intent scores → combat:2, character:1, …
41
51
  roles → Main + Managers + Controllers + Types
42
- user functions→ kept in the matching Controller (not discarded)
43
- ```
44
-
45
- Generated files start with that trace:
46
-
47
- ```luau
48
- -- tag server → Script (service)
49
- -- intents combat:2, character:1
50
- -- roles Main, CombatController, CombatTypes
51
52
  ```
52
53
 
53
54
  | Evidence in the C++ | Role |
@@ -61,50 +62,6 @@ Generated files start with that trace:
61
62
  | Domain shapes / stats | `{Service}Types` (`export type`, `return {}`) |
62
63
  | Wiring | `Main.Start` / `Main.Stop` |
63
64
 
64
- If the C++ creates Coins/Level, CacheController is generated (higher quality than copying `CreateLeaderstats`). Combat logic is **not** rewritten into leaderstats — `ApplyDamage` stays in `CombatController.luau`.
65
-
66
- ## What leaderstats becomes
67
-
68
- ```
69
- src/server/leaderstats.server.cpp
70
- ```
71
-
72
- ```
73
- out/server/LeaderStats/
74
- init.server.luau
75
- Main.luau
76
- PlayersManager.luau
77
- CacheController.luau
78
- LeaderStatsTypes.luau
79
- ```
80
-
81
- ## What combat becomes
82
-
83
- ```
84
- src/server/combat.server.cpp -- TakeDamage, Humanoid
85
- ```
86
-
87
- ```
88
- out/server/Combat/
89
- init.server.luau
90
- Main.luau
91
- CombatController.luau -- your ApplyDamage / OnHit
92
- CombatTypes.luau
93
- ```
94
-
95
- No PlayersManager unless you actually listen to players. No CacheController unless you actually create value Instances.
96
-
97
- ## ForeverHD-style rules
98
-
99
- - PascalCase folders and modules; camelCase locals
100
- - `--!strict` everywhere
101
- - Public API `Start` / `Stop`
102
- - Janitor owns connections in the Manager
103
- - Types modules `return {}`
104
- - Transparent `require(script.Parent.X)`
105
-
106
- ## Config
107
-
108
- `cluaupp.config.json`: `"architecture": true` (default). `"architecture": false` forces 1:1 dumps (or use `.legacy.server.cpp` / `.legacy.client.cpp` per file).
65
+ Switching back to 1:1 deletes the stale `LeaderStats/` / `DataBoot/` folders on the next `cluaupp build`.
109
66
 
110
- See [organization](cpp-organization.md) and [comparison](comparison.md).
67
+ How to **write** a system, tags, and module-style OOP: [OOP structure](oop/index.md). Copy-paste systems: [Examples](examples/index.md). Also [organization](cpp-organization.md) and [comparison](comparison.md).
package/docs/cli.md CHANGED
@@ -23,13 +23,12 @@ cluaupp init my-game
23
23
 
24
24
  ## `cluaupp build [folder]`
25
25
 
26
- Transpiles `src/**/*.{cpp,h,hpp}` into `out/`. Script files become PascalCase **service folders** (`LeaderStats/Main.luau`, `PlayersManager.luau`, `CacheController.luau`, `LeaderStatsTypes.luau`) plus `init.server.luau` for Rojo. Shared `const` headers become `Config.luau`.
26
+ Transpiles `src/**/*.{cpp,h,hpp}` into `out/`. One tagged `.cpp` becomes one Luau instance (`leaderstats.server.luau`, `hud.client.luau`). Shared untagged files become ModuleScripts. Set `"architecture": true` for the old PascalCase service folders.
27
27
 
28
- - `--!strict` on every module
29
- - `#include "file.h"` inlines that header into the current file
28
+ - `--!strict` only with `#pragma strict` or `"strict": true`
29
+ - `#include "file.h"` becomes `require(ReplicatedStorage.Cluaupp...)` / `require(ServerScriptService.Cluaupp...)` for shared/server modules
30
30
  - `#include <cluaupp/roblox.hpp>` is ignored
31
- - `.h` / `.hpp` with a sibling `.cpp` are not emitted twice
32
- - `new Folder(parent)` in a stats system becomes `CacheController.Ensure`
31
+ - `.h` / `.hpp` emit a type ModuleScript (`export type` + typed table). A sibling `.cpp` becomes `*Impl.luau` (the construction); the header binds those functions.
33
32
  - A parse error exits with code 1 and `file:line:column`
34
33
  - After emit, **orphans in `out/` are removed** (source deleted → matching Luau deleted). `out/` itself is never wiped, so a running Rojo serve keeps the live tree.
35
34
  - `libs/` and `include/cluaupp` are synced by writing missing/changed files only. They are **never** deleted as a folder — Rojo 7 unwrap-crashes if `libs/ArrayIndexer` vanishes while serving.
@@ -41,7 +40,7 @@ cluaupp build ./my-game
41
40
 
42
41
  ## `cluaupp watch [folder]`
43
42
 
44
- Runs a `build` and rebuilds when anything under `src/` changes, including deletes. Parse errors are printed; the watcher stays alive and **does not write `out/`** until the project compiles cleanly (Studio keeps the last good scripts). Rebuilds are debounced and do **not** recopy `libs/`. Deleted `.cpp` files prune their `out/` artifacts on the next successful compile.
43
+ Runs a compile (without copying `libs/`) and rebuilds when anything under `src/` changes, including deletes. Parse errors are printed; the watcher stays alive and **does not write `out/`** until the project compiles cleanly (Studio keeps the last good scripts). A second watcher in the same game exits. Deleted `.cpp` files prune their `out/` artifacts on the next successful compile.
45
44
 
46
45
  ## `cluaupp --version` / `cluaupp -v`
47
46
 
@@ -6,9 +6,9 @@
6
6
 
7
7
  Both are source-to-source. Neither goes through WASM. Generated Luau calls the Roblox API directly.
8
8
 
9
- The difference is **what Studio receives**. roblox-ts stops at the filename key (`*.server.ts` → Script). Cluaupp uses that key **and** reads the AST so a combat system is not emitted as a fake leaderstats. See [Architecture](architecture.md).
9
+ By default Cluaupp matches that filename key: `*.server.cpp` → one Script, `*.client.cpp` one LocalScript, untagged ModuleScript. The ForeverHD folder split is opt-in (`"architecture": true`). See [Architecture](architecture.md).
10
10
 
11
- Current Luau has [`local`, `const`, and `--!strict`](https://luau.org/getting-started). Cluaupp emits that on purpose: `const int` in C++ becomes `const x = ...` in Luau.
11
+ Current Luau has [`local`, `const`, and `--!strict`](https://luau.org/getting-started). Cluaupp emits `const` from C++ `const`. `--!strict` is opt-in (`#pragma strict` or `"strict": true`).
12
12
 
13
13
  ## vs C++ → WASM → Luau (RBX-CPP / Emscripten)
14
14
 
@@ -33,5 +33,5 @@ is exactly what Studio expects, not a parallel runtime.
33
33
  | Goal | Tool |
34
34
  | --- | --- |
35
35
  | Game in TypeScript | roblox-ts |
36
- | Game in C++, clear Roblox API, Luau `--!strict` | **Cluaupp** |
36
+ | Game in C++, clear Roblox API | **Cluaupp** |
37
37
  | Full native C++ (templates, STL, engines) | not Cluaupp today |
package/docs/config.md CHANGED
@@ -6,17 +6,17 @@ File: `cluaupp.config.json` at the game root (next to `src/`).
6
6
  {
7
7
  "rootDir": "src",
8
8
  "outDir": "out",
9
- "strict": true,
10
- "architecture": true
9
+ "strict": false,
10
+ "architecture": false
11
11
  }
12
12
  ```
13
13
 
14
14
  | Field | Default | Effect |
15
15
  | --- | --- | --- |
16
16
  | `rootDir` | `"src"` | Where the `.cpp` / `.h` / `.hpp` files live |
17
- | `outDir` | `"out"` | Where services and modules are written |
18
- | `strict` | `true` | Prefix `--!strict` on every generated file |
19
- | `architecture` | `true` | Emit PascalCase service folders (`LeaderStats/Main.luau`, …) instead of one dump per `.cpp` |
17
+ | `outDir` | `"out"` | Where Luau is written |
18
+ | `strict` | `false` | Prefix `--!strict` on generated files (overridden by `#pragma strict` / `#pragma nstrict`) |
19
+ | `architecture` | `false` | If `true`, emit PascalCase service folders (`LeaderStats/Main.luau`, …) instead of one Luau per `.cpp` |
20
20
 
21
21
  If the file is missing, those defaults apply.
22
22
 
@@ -28,4 +28,4 @@ The template ships `default.project.json` mapping:
28
28
  - `out/client` → `StarterPlayer.StarterPlayerScripts.Cluaupp`
29
29
  - `out/shared` → `ReplicatedStorage.Cluaupp`
30
30
 
31
- `*.server.luau` and `*.client.luau` files are classified by Rojo as Script and LocalScript. A folder with `init.server.luau` becomes a Script named after the folder (`LeaderStats`) with ModuleScript children (`Main`, `PlayersManager`, `CacheController`, `LeaderStatsTypes`).
31
+ `*.server.cpp` becomes `*.server.luau` (Script). `*.client.cpp` becomes `*.client.luau` (LocalScript). Untagged files become ModuleScripts.
@@ -9,7 +9,7 @@ The subset is intentional. What exists is enough for game scripts; what is missi
9
9
 
10
10
  ## Supported
11
11
 
12
- - Functions, prototypes (headers only), `if` / `else` / `while` / range-`for`
12
+ - Functions, prototypes (headers only), `if` / `else` / `while` / range-`for` / `switch` (`case`, `default`, `break`)
13
13
  - `new Class(parent)`, `GetService<T>()`, `::` statics (`CFrame::lookAt`, `Enum::Material::Plastic`)
14
14
  - `->` methods and properties, `.` members, `Connect`
15
15
  - `const`, `auto`, `nullptr`, arithmetic, `&&` `||` `!=`
@@ -18,7 +18,7 @@ The subset is intentional. What exists is enough for game scripts; what is missi
18
18
 
19
19
  ## Not supported (yet)
20
20
 
21
- Full C++: templates besides `GetService<T>`, `class` bodies as emitted types, `std::`, overloading as two runtimes, `switch`, C-style `for`, macros, pointer arithmetic.
21
+ Full C++: templates besides `GetService<T>`, `class` bodies as emitted types, `std::`, overloading as two runtimes, C-style `for`, macros, pointer arithmetic.
22
22
 
23
23
  If you need a custom type, it is usually a **ModuleScript in shared** (a `.cpp` of functions) or a Wally package, not a C++ class the compiler would lower to a metatable.
24
24
 
@@ -45,12 +45,16 @@ CluauppLibs already contains the full Janitor, Fusion, Cmdr, DataServiceV2, …
45
45
  #include <cluaupp/libs/dataservice.hpp>
46
46
 
47
47
  void Grant(Player* player, int amount) {
48
- auto coins = DataService::Get(player, "Currencies.Coins");
49
- DataService::Set(player, "Currencies.Coins", coins + amount);
48
+ Data* data = DataService::Server.WaitFor(player);
49
+ if (data == nullptr) {
50
+ return;
51
+ }
52
+ int coins = data->Get(DataService::Server.Paths.Currencies.Money);
53
+ data->Set(DataService::Server.Paths.Currencies.Money, coins + amount);
50
54
  }
51
55
  ```
52
56
 
53
- Keep path strings in `config.h`. Match the tokens your DataServiceV2 template already uses (`DataService.Paths.Currencies.Coins` in Luau).
57
+ `Paths.Currencies.Money` exists because **your** Template passed to `Init` had that field. Full copies: [Examples](examples/index.md).
54
58
 
55
59
  ## Performance notes
56
60
 
@@ -68,4 +72,4 @@ Keep path strings in `config.h`. Match the tokens your DataServiceV2 template al
68
72
  5. **Headers declare, scripts define.** Prototypes in `.h`, bodies in `.cpp`.
69
73
  6. **Do not share mutable statics across server and client** — use Net or DataService.
70
74
 
71
- See also: [syntax](syntax.md), [libraries](libraries.md), [comparison](comparison.md).
75
+ See also: [syntax](syntax.md), [print and cout](print-cout.md), [libraries](libraries/index.md), [OOP](oop/index.md), [examples](examples/index.md), [comparison](comparison.md).
@@ -5,7 +5,7 @@ sidebar_position: 13
5
5
 
6
6
  # Organization
7
7
 
8
- A Cluaupp game is laid out like a roblox-ts project on disk. The **output** is not a dump: `cluaupp build` turns each system into a PascalCase service folder (Main, Manager, Controller, Types). See [Architecture](architecture.md).
8
+ A Cluaupp game is laid out like a roblox-ts project on disk. One tagged `.cpp` becomes one Luau instance (`leaderstats.server.luau`, `hud.client.luau`). See [Architecture](architecture.md).
9
9
 
10
10
  ```
11
11
  src/
@@ -47,7 +47,7 @@ const string REMOTE_COINS = "Coins";
47
47
 
48
48
  `leaderstats.server.cpp` creates leaderstats. It does not also open the shop UI. Name files after the system: `inventory.server.cpp`, `shop.client.cpp`.
49
49
 
50
- `*.server.cpp` / `*.client.cpp` are **tags** (the same keys roblox-ts uses). Untagged `.cpp` is a ModuleScript. `.legacy.server.cpp` / `.legacy.client.cpp` skip the service split. See [Architecture](architecture.md).
50
+ `*.server.cpp` / `*.client.cpp` are **tags** (the same keys roblox-ts uses). Untagged `.cpp` is a ModuleScript. Set `"architecture": true` only if you want the old PascalCase folder split. See [Architecture](architecture.md) and [OOP structure](oop/index.md).
51
51
 
52
52
  ## CluauppLibs vs extra Wally
53
53
 
@@ -58,4 +58,6 @@ const string REMOTE_COINS = "Coins";
58
58
 
59
59
  Do not install a second Janitor from Wally unless you have a reason — CluauppLibs already has howmanysmall/Janitor. DataServiceV2 still bundles its own janitor/quicknet/signal inside the DataService folder.
60
60
 
61
+ How-tos: [Libraries](libraries/index.md). Service layout: [OOP](oop/index.md). Copy-paste: [Examples](examples/index.md).
62
+
61
63
  Next: [advanced Cluaupp](cpp-advanced.md).
@@ -9,7 +9,7 @@ Safety in Cluaupp is not a sandbox flag. It is a set of habits the compiler and
9
9
 
10
10
  ## 1. Never trust the client
11
11
 
12
- [Net](libraries.md) lets a client `FireServer`. The server must validate:
12
+ [Net](libraries/net.md) lets a client `FireServer`. The server must validate:
13
13
 
14
14
  ```cpp
15
15
  void OnBuy(Player* player, int productId) {
@@ -17,19 +17,23 @@ void OnBuy(Player* player, int productId) {
17
17
  return;
18
18
  }
19
19
  int price = PriceOf(productId);
20
- int coins = DataService::Get(player, "Currencies.Coins");
20
+ Data* data = DataService::Server.WaitFor(player);
21
+ if (data == nullptr) {
22
+ return;
23
+ }
24
+ int coins = data->Get(DataService::Server.Paths.Currencies.Money);
21
25
  if (coins < price) {
22
26
  return;
23
27
  }
24
- DataService::Set(player, "Currencies.Coins", coins - price);
28
+ data->Set(DataService::Server.Paths.Currencies.Money, coins - price);
25
29
  }
26
30
  ```
27
31
 
28
- Do not store coins only on the client. Do not let the client pass the new coin total — pass the *intent* (`productId`).
32
+ Do not store coins only on the client. Do not let the client pass the new coin total — pass the *intent* (`productId`). Full systems: [Shop](examples/shop.md), [Combat](examples/combat.md).
29
33
 
30
34
  ## 2. Clean up with Janitor
31
35
 
32
- Every `Connect` that outlives a player, a GUI, or a tool needs a Janitor. Leaving a step, destroying a character, or closing a menu should `Cleanup()` or `LinkToInstance`.
36
+ Every `Connect` that outlives a player, a GUI, or a tool needs a [Janitor](libraries/janitor.md). Leaving a step, destroying a character, or closing a menu should `Cleanup()` or `LinkToInstance`.
33
37
 
34
38
  ```cpp
35
39
  auto* janitor = new Janitor();
@@ -45,7 +49,7 @@ Leaked connections duplicate effects: double coins, stacked cameras, lingering h
45
49
 
46
50
  ## 4. One writer for persisted data
47
51
 
48
- [DataServiceV2](https://wally.run/package/kartzrbx/dataservicev2) distinguishes `Get()` (merged, includes transient admin overlays) from `GetPersisted()` (what ProfileStore will save). Use `SetTransient` for test panels so you never persist cheat values. Only the server writes persisted paths.
52
+ [DataService](libraries/dataservice.md) distinguishes `Get()` (merged, includes transient admin overlays) from `GetPersisted()` (what ProfileStore will save). Use `SetTransient` for test panels so you never persist cheat values. Only the server writes persisted paths. The save **shape** is your Template — the library does not ship `Currencies`.
49
53
 
50
54
  ## 5. Buffers, not ad-hoc strings
51
55
 
@@ -55,4 +59,4 @@ Leaked connections duplicate effects: double coins, stacked cameras, lingering h
55
59
 
56
60
  Remote names (`Net::Event("Coins")`) are public protocol. Keep them `const`, short, and unique. Changing a name without a migration breaks old clients.
57
61
 
58
- Next: [organization](cpp-organization.md).
62
+ Next: [organization](cpp-organization.md), [OOP](oop/index.md), [Examples](examples/index.md).
package/docs/cpp-types.md CHANGED
@@ -46,7 +46,7 @@ player.Name = "Kartz"
46
46
  player:FindFirstChild("leaderstats")
47
47
  ```
48
48
 
49
- There is no pointer arithmetic, no `delete`, no `std::unique_ptr`. Lifetime is Roblox’s: parented Instances live until `Destroy` or until a [Janitor](libraries.md) cleans them.
49
+ There is no pointer arithmetic, no `delete`, no `std::unique_ptr`. Lifetime is Roblox’s: parented Instances live until `Destroy` or until a [Janitor](libraries/janitor.md) cleans them.
50
50
 
51
51
  ## `nullptr`
52
52
 
@@ -0,0 +1,5 @@
1
+ {
2
+ "label": "Examples",
3
+ "position": 21,
4
+ "collapsed": false
5
+ }