cluaupp 0.1.4 → 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.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,18 @@
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
+
3
10
  ## 0.1.4
4
11
 
5
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()`).
6
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.
7
16
 
8
17
  ## 0.1.3
9
18
 
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [![Node.js](https://img.shields.io/node/v/cluaupp.svg)](https://nodejs.org)
13
13
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
14
14
 
15
- 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.
16
16
 
17
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()`.
18
18
 
@@ -66,12 +66,12 @@ rojo serve
66
66
  Connect the Rojo plugin in Roblox Studio. Edit `src/**/*.{cpp,h,hpp}`, run `cluaupp watch` to rebuild on save.
67
67
 
68
68
  ```
69
- src/server/*.server.cpp → out/server/LeaderStats/ Script + ModuleScripts
70
- src/client/*.client.cpp → out/client/*.client.luau LocalScript (or a service folder)
71
- 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
72
72
  ```
73
73
 
74
- 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) and [OOP structure](docs/oop/index.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).
75
75
 
76
76
  ## Documentation
77
77
 
@@ -84,7 +84,7 @@ A tiny `leaderstats.server.cpp` becomes `Main` / `PlayersManager` / `CacheContro
84
84
  | [Syntax](docs/syntax.md) | C++ subset → Luau (`local`, `const`, types) |
85
85
  | [print and cout](docs/print-cout.md) | `cout <<`, `cout::warn`, `endl` |
86
86
  | [Roblox API](docs/roblox-api.md) | Vector3, CFrame, UDim2, GetService, Instance.new |
87
- | [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
88
  | [OOP structure](docs/oop/index.md) | File tags, services, modules, structs |
89
89
  | [Libraries](docs/libraries/index.md) | DataService Init, Janitor, Promise, Net |
90
90
  | [Examples](docs/examples/index.md) | Leaderstats, combat validation, shop, HUD, sword |
package/docs/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  8. [Safety](cpp-safety.md) — client trust, Janitor, Net, DataService
11
11
  9. [Organization](cpp-organization.md) — server / client / shared
12
12
  10. [Advanced](cpp-advanced.md) — `::` vs `:`, Wally, performance
13
- 11. [Architecture](architecture.md) — PascalCase services, Types modules, vs roblox-ts dumps
13
+ 11. [Architecture](architecture.md) — one file in, one file out; opt-in ForeverHD folders
14
14
  12. [OOP structure](oop/index.md) — file tags, services, modules, structs
15
15
  13. [Libraries](libraries/index.md) — DataService Init, Janitor, Promise, Net, more
16
16
  14. [Examples](examples/index.md) — leaderstats, combat validation, shop, HUD, sword
@@ -3,54 +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` | **Script** RunContext Server | `Combat/init.luau` + `init.meta.json` |
28
- | `hud.client.cpp` | **LocalScript** | `Hud/init.client.luau` |
29
- | `tools.plugin.cpp` | **Script** RunContext Plugin | `Tools/init.luau` + `init.meta.json` |
30
- | `boot.legacy.cpp` | Legacy Script | `boot.server.luau` |
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) |
31
30
  | `boot.legacy.server.cpp` | Legacy Script | `boot.server.luau` |
32
- | `boot.legacy.client.cpp` | Legacy LocalScript | `boot.client.luau` |
33
- | `boot.legacy.plugin.cpp` | Plugin | `boot.luau` + Plugin meta |
34
31
  | `damage.cpp` (no tag) | **ModuleScript** | `Damage.luau` |
35
32
 
36
- Trivial entry files (`init.client.cpp` that only `print`) stay a single LocalScript (`init.client.luau`). The planner does not invent Managers for a hello-world.
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
+ ```
40
+
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.
37
42
 
38
- ## 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()`.
39
46
 
40
47
  ```
41
48
  filename key → server | client | module | legacy
42
49
  AST features → GetService, Instance.new, methods, identifiers
43
50
  intent scores → combat:2, character:1, …
44
51
  roles → Main + Managers + Controllers + Types
45
- user functions→ kept in the matching Controller (not discarded)
46
- ```
47
-
48
- Generated files start with that trace:
49
-
50
- ```luau
51
- -- tag server → Script (service)
52
- -- intents combat:2, character:1
53
- -- roles Main, CombatController, CombatTypes
54
52
  ```
55
53
 
56
54
  | Evidence in the C++ | Role |
@@ -64,54 +62,6 @@ Generated files start with that trace:
64
62
  | Domain shapes / stats | `{Service}Types` (`export type`, `return {}`) |
65
63
  | Wiring | `Main.Start` / `Main.Stop` |
66
64
 
67
- 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`.
68
-
69
- The domain controller keeps **every** user function. CacheController is generated beside it; it must not delete `SetupPlayerManager` while `init` still calls that name. `GetChangedSignal(Paths.Currencies)` stays in `DataController`.
70
-
71
- ## What leaderstats becomes
72
-
73
- ```
74
- src/server/leaderstats.server.cpp
75
- ```
76
-
77
- ```
78
- out/server/LeaderStats/
79
- init.luau
80
- init.meta.json
81
- Main.luau
82
- PlayersManager.luau
83
- CacheController.luau
84
- LeaderStatsTypes.luau
85
- ```
86
-
87
- ## What combat becomes
88
-
89
- ```
90
- src/server/combat.server.cpp -- TakeDamage, Humanoid
91
- ```
92
-
93
- ```
94
- out/server/Combat/
95
- init.luau
96
- init.meta.json
97
- Main.luau
98
- CombatController.luau -- your ApplyDamage / OnHit
99
- CombatTypes.luau
100
- ```
101
-
102
- No PlayersManager unless you actually listen to players. No CacheController unless you actually create value Instances.
103
-
104
- ## ForeverHD-style rules
105
-
106
- - PascalCase folders and modules; camelCase locals
107
- - `--!strict` everywhere
108
- - Public API `Start` / `Stop`. `Start` is idempotent (`Stop` first). Domain `Stop` is `janitor:Cleanup()` (unbind, janitor stays reusable). `OnClose` / `Destroy` stay for `BindToClose`. `PlayersManager.Stop` disconnects and runs `onLeave`. `CacheController.ClearAll` drops the cache.
109
- - Janitor owns connections in the Manager
110
- - Module layout in generated Luau (no section banners): requires, types, constants, variables, functions, cleanup, return.
111
- - Transparent `require(script.Parent.X)`
112
-
113
- ## Config
114
-
115
- `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`.
116
66
 
117
- How to **write** a service, 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).
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.luau` and `init.meta.json` (`RunContext.Server`) 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.
@@ -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.cpp` becomes a folder with `init.luau` + `init.meta.json` (`className` Script, `RunContext` Server). `.client` stays LocalScript via `init.client.luau`. A `.legacy.server.cpp` dump is still `*.server.luau` (Legacy).
31
+ `*.server.cpp` becomes `*.server.luau` (Script). `*.client.cpp` becomes `*.client.luau` (LocalScript). Untagged files become ModuleScripts.
@@ -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) and [OOP structure](oop/index.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
 
@@ -66,7 +66,8 @@ my-game/
66
66
  shared/config.h
67
67
  shared/config.cpp
68
68
  out/ ← generated Luau (do not edit)
69
- server/LeaderStats/ Main, PlayersManager, CacheController, Types
69
+ server/leaderstats.server.luau
70
+ client/init.client.luau
70
71
  shared/Config.luau
71
72
  ```
72
73
 
package/docs/intro.md CHANGED
@@ -5,7 +5,7 @@ sidebar_position: 1
5
5
 
6
6
  # Cluaupp
7
7
 
8
- **The definitive merge of C++ and modern Luau.** You write a C++ subset. Cluaupp emits [Luau](https://luau.org/getting-started) with `--!strict`, `local`, and `const`, and calls the Roblox API the way Studio does.
8
+ **The definitive merge of C++ and modern Luau.** You write a C++ subset. Cluaupp emits [Luau](https://luau.org/getting-started) with `local` and `const` (and `--!strict` when you opt in), and calls the Roblox API the way Studio does.
9
9
 
10
10
  This site is built with [Moonwave](https://eryn.io/moonwave/) for local markdown (`npm run docs`). The **public** site is generated into `site/` and deployed to [GitHub Pages](https://kartzrbx.github.io/Cluaupp/) (Learn tabs, OOP, Examples, API). The language is in the same spirit as [roblox-ts](https://roblox-ts.com): a familiar syntax, a restricted subset, readable output.
11
11
 
@@ -16,34 +16,33 @@ The **filename** decides the Roblox instance. This is the same key idea as roblo
16
16
  | `Boot.legacy.server.cpp` | Script | **Legacy** |
17
17
  | `Boot.legacy.client.cpp` | LocalScript | Legacy |
18
18
  | `Damage.cpp` (no tag) | **ModuleScript** | — |
19
+ | `LeaderstatsServer.h` | **ModuleScript** (types) | — |
20
+ | `LeaderstatsServer.cpp` (sibling of `.h`) | **ModuleScript** (`*Impl`) | — |
19
21
 
20
- ## Server is not Legacy
22
+ ## One file in, one file out
21
23
 
22
- `.server.cpp` is **not** `init.server.luau`. Rojo maps `*.server.luau` to a Script with RunContext **Legacy**. Cluaupp emits:
24
+ Rojo infers the instance from the filename key: `*.server.luau` is a Script, `*.client.luau` is a LocalScript, untagged `.luau` is a ModuleScript.
23
25
 
24
26
  ```
25
- out/server/LeaderstatsServer/
26
- init.luau
27
- init.meta.json -- className Script, RunContext Server
27
+ src/server/boot/DataBoot.server.cpp → out/server/boot/DataBoot.server.luau
28
+ src/client/boot/DataBoot.client.cpp → out/client/boot/DataBoot.client.luau
29
+ src/shared/damage.cpp → out/shared/Damage.luau
30
+ src/server/services/leaderstats/LeaderstatsServer.h → LeaderstatsServer.luau (export type)
31
+ src/server/services/leaderstats/LeaderstatsServer.cpp → LeaderstatsServerImpl.luau
28
32
  ```
29
33
 
30
- `.legacy.server.cpp` is the 1:1 dump that *does* become Legacy.
31
-
32
- `.client.cpp` stays `init.client.luau` (LocalScript). Do not add `init.meta.json` on the client boot.
34
+ `.legacy.server.cpp` still emits a Legacy Script (`boot.server.luau`). `.client.cpp` stays a LocalScript. Do not invent `init.meta.json` on the default 1:1 path.
33
35
 
34
36
  ## Where files live
35
37
 
36
38
  ```
37
- src/server/.../*.server.cpp → out/server (ServerScriptService)
38
- src/client/.../*.client.cpp → out/client (StarterPlayerScripts)
39
- src/shared/.../*.cpp → out/shared (ReplicatedStorage)
39
+ src/server/.../*.server.cpp → out/server (ServerScriptService.Cluaupp)
40
+ src/client/.../*.client.cpp → out/client (StarterPlayerScripts.Cluaupp)
41
+ src/shared/.../*.cpp → out/shared (ReplicatedStorage.Cluaupp)
40
42
  ```
41
43
 
42
- Name the **system**, not `init.server.cpp`. `LeaderstatsServer.server.cpp` and `DataBoot.server.cpp` are two services.
43
-
44
- ## Skip the planner
44
+ Name the **system**, not `init.server.cpp`. `LeaderstatsServer.server.cpp` and `DataBoot.server.cpp` are two files.
45
45
 
46
- - `"architecture": false` in `cluaupp.config.json`, or
47
- - `.legacy.server.cpp` / `.legacy.client.cpp` per file
46
+ ## Opt-in planner
48
47
 
49
- Use legacy only when you want one Luau file with no Main / Controller split.
48
+ `"architecture": true` in `cluaupp.config.json` restores PascalCase service folders (`Main`, Controller, Types). Default is off.
package/docs/oop/index.md CHANGED
@@ -11,12 +11,12 @@ The **live site** (not just these markdown files) is GitHub Pages:
11
11
  - [Guide → OOP](https://kartzrbx.github.io/Cluaupp/guide/oop.html)
12
12
  - [Examples](https://kartzrbx.github.io/Cluaupp/guide/examples.html)
13
13
 
14
- Cluaupp does **not** compile custom C++ `class` types yet. “OOP” here is how you **lay out systems** so Studio gets services, modules, and lifecycle — the same idea as roblox-ts filename keys + Flamework `@Service`, without decorators.
14
+ Cluaupp does **not** compile custom C++ `class` types yet. “OOP” here is how you **lay out systems** so Studio gets Script / LocalScript / ModuleScript from the filename tag — the same idea as roblox-ts. Flamework-style Start/Stop folders are opt-in (`"architecture": true`).
15
15
 
16
16
  | Page | What you learn |
17
17
  | --- | --- |
18
18
  | [File tags](file-tags.md) | `.server` / `.client` / `.plugin` / `.legacy` / untagged |
19
- | [Services](services.md) | One `.server.cpp` → Main, Controller, Start / Stop |
19
+ | [Services](services.md) | One `.server.cpp` → one `.server.luau` |
20
20
  | [Modules](modules.md) | Untagged files, structs, named functions as methods |
21
21
 
22
22
  Planner details: [Architecture](../architecture.md). Folder layout: [Organization](../cpp-organization.md). Full services: [Examples](../examples/index.md).
@@ -25,7 +25,9 @@ int DoubleCoins(int coins) {
25
25
  out/shared/util/Coins.luau -- ModuleScript, exported functions
26
26
  ```
27
27
 
28
- Shared **data and constants** belong in headers (`#include "TemplateData.hpp"`) they are inlined. Untagged `.cpp` is for a ModuleScript other Luau can `require`. Prefer headers for data and tagged `.server.cpp` / `.client.cpp` for behavior.
28
+ Quoted `#include "TemplateData.hpp"` is not inlined when the header has a sibling `.cpp` or is a shared module: `cluaupp build` emits `require(ReplicatedStorage.Cluaupp.constants.TemplateData)` / `require(ServerScriptService.Cluaupp.configurations.PlayerDataVersion)` (Rojo roots from `default.project.json`), never `script.Parent.Parent.shared`.
29
+
30
+ `.h` / `.hpp` are **type modules**. A service header becomes `export type Name = { init: (self: Name) -> (), … }` and a typed table. The sibling `.cpp` is the construction (`NameImpl.luau`); the header `require`s that impl and binds the functions. Data-only structs still emit a constructor so `TemplateData()` works. Untagged `.cpp` without a header is a ModuleScript other Luau can `require`. Prefer headers for the public type, tagged `.server.cpp` / `.client.cpp` for scripts, and the sibling `.cpp` for method bodies.
29
31
 
30
32
  ## Structs = data, not classes
31
33
 
@@ -5,7 +5,7 @@ sidebar_position: 3
5
5
 
6
6
  # Services
7
7
 
8
- Write **one tagged file per system**. Cluaupp reads the AST and emits a PascalCase folder: `Main`, managers, controllers, `*Types`.
8
+ Write **one tagged file per system**. Cluaupp emits **one** Luau instance: `LeaderstatsServer.server.luau` from `LeaderstatsServer.server.cpp`. It does not invent Main / Controller / Types unless `"architecture": true`.
9
9
 
10
10
  ## Example: leaderstats
11
11
 
@@ -44,29 +44,22 @@ void init() {
44
44
  Typical output:
45
45
 
46
46
  ```
47
- out/server/LeaderstatsServer/
48
- init.luau -- Script, RunContext Server
49
- init.meta.json
50
- Main.luau -- Start / Stop
51
- PlayersManager.luau -- PlayerAdded + Janitor
52
- DataController.luau -- your WaitFor / GetChangedSignal
53
- CacheController.luau -- if you create IntValue folders
54
- LeaderstatsServerTypes.luau
47
+ out/server/services/leaderstats/LeaderstatsServer.server.luau
55
48
  ```
56
49
 
57
- Your functions stay in the matching controller. The planner does not drop `SetupPlayerManager` because `init` still calls it.
50
+ Your functions stay in that file. `init()` runs at the end. There is no fake `Main` that only forwards to a Controller.
58
51
 
59
52
  ## Lifecycle
60
53
 
61
- Generated `Main` exposes `Start` / `Stop`. Managers own a Janitor. `Stop` cleans connections.
54
+ You own `init` and Janitor cleanup in the same file. You do not write `class LeaderstatsServer` name the **file** `LeaderstatsServer.server.cpp` and keep **functions** as the public API.
62
55
 
63
- You do not write `class LeaderstatsServer` name the **file** `LeaderstatsServer.server.cpp` and keep **functions** as the public API.
56
+ `"architecture": true` is the old ForeverHD split (`Main.Start` / `Main.Stop`, Managers, Types). Leave it off unless you want that.
64
57
 
65
58
  ## Boot vs gameplay
66
59
 
67
60
  Keep DataService `Init` in `DataBoot.server.cpp` / `DataBoot.client.cpp`. Keep leaderstats / combat in their own `.server.cpp`. Services `WaitFor` after boot has run.
68
61
 
69
- ## What becomes which role
62
+ ## Opt-in roles (`"architecture": true`)
70
63
 
71
64
  | Your C++ | Generated role |
72
65
  | --- | --- |
@@ -78,6 +71,6 @@ Keep DataService `Init` in `DataBoot.server.cpp` / `DataBoot.client.cpp`. Keep l
78
71
  | `UserInputService` | `InputController` |
79
72
  | wiring | `Main.Start` / `Main.Stop` |
80
73
 
81
- A tiny `print` in `init.client.cpp` stays a single LocalScript. The planner does not invent Managers for hello-world.
74
+ A tiny `print` in `init.client.cpp` stays a single LocalScript.
82
75
 
83
76
  Copy-paste: [Examples](../examples/index.md).
package/docs/syntax.md CHANGED
@@ -2,15 +2,16 @@
2
2
 
3
3
  Cluaupp is not a full C++ compiler. It is a **subset** aimed at Roblox scripts, in the same spirit as roblox-ts (restricted TypeScript → Luau).
4
4
 
5
- Generated Luau follows the current language: [`--!strict`](https://luau.org/getting-started), `local`, `const`, and `const function`. Injected `require` / `GetService` lines are `const`.
5
+ Generated Luau follows the current language: [`local`](https://luau.org/getting-started), `const`, and `const function`. Injected `require` / `GetService` lines are `const`. `--!strict` is emitted only when the file has `#pragma strict` (or `"strict": true` in config).
6
6
 
7
7
  ## Files
8
8
 
9
9
  - Extensions: `.cpp`, `.h`, `.hpp` (also `.cc`, `.hh`)
10
- - Quoted `#include "file.h"` is inlined (C preprocessor)
10
+ - Quoted `#include "file.h"` becomes a Rojo `require` (or is inlined for a header that belongs to the same `.cpp`)
11
11
  - `#include <cluaupp/roblox.hpp>` and `<cluaupp/libs/*.hpp>` are IntelliSense only; library headers also inject `require(CluauppLibs.*)`
12
- - Other `#` lines (`#pragma once`) are ignored
13
- - Function prototypes (`void foo();`) are skipped; only functions with a body are emitted
12
+ - `#pragma once` is ignored
13
+ - `#pragma strict` / `#pragma nstrict` control `--!strict` for that compilation unit
14
+ - Function prototypes in a `.h` / `.hpp` become `export type` fields (`init: (self: Name) -> ()`). Only `.cpp` files emit function bodies.
14
15
 
15
16
  ## Functions
16
17
 
@@ -199,6 +200,6 @@ Full table and IntelliSense notes: [print and cout](print-cout.md).
199
200
 
200
201
  ## Not supported yet
201
202
 
202
- Custom C++ classes, generic templates besides `GetService<T>`, pointer arithmetic, `std::`, overloading, macros (except skipping `#` lines).
203
+ Custom C++ classes, generic templates besides `GetService<T>`, pointer arithmetic, `std::`, overloading, macros (except `#pragma strict` / `#pragma nstrict` / `#pragma once`).
203
204
 
204
205
  If you need one of those patterns, open an issue with the C++ and the expected Luau.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cluaupp",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Cluaupp — the definitive merge of C++ and modern Luau. Source-to-source transpiler with first-class Roblox APIs.",
5
5
  "author": "KartzDev",
6
6
  "license": "MIT",