cluaupp 0.2.2 → 0.2.3

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
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.3
6
+
7
+ - Parser accepts `(void)x`, `static_cast<T>(x)`, `static constexpr` fields, and lambdas (`[](Player* p) { ... }`, `[&]`, `[=]`) so `Connect` / `BindToClose` compile without named-function wrappers.
8
+ - Parser keeps `LuaArray<T>` / `vector<T>` field types on structs (`HotBar` / `Storage` on a Template).
9
+ - `string_concat(...)` joins to Luau `..` (alongside string `+`).
10
+ - Cursor is not a licensed host for Microsoft `ms-vscode.cpptools`. Cluaupp no longer writes `C_Cpp.*` settings or `c_cpp_properties.json`; `watch` strips leftover keys and marks cpptools as unwanted. C++ completion stays clangd.
11
+ - Docs site is a C++-class handbook (syntax through lambdas and Luau `--!strict`). Per-class and per-enum dump pages are gone; engine members stay on create.roblox.com.
12
+
5
13
  ## 0.2.2
6
14
 
7
15
  - Header modules with a sibling `.cpp` now re-export those functions (`startingCoins` from `config.cpp` lands on `config.luau` via `configImpl`). The impl no longer `require`s its own header (`ReplicatedStorage.config`).
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  **The definitive merge of C++ and modern Luau.**
8
8
 
9
- [Docs](https://kartzrbx.github.io/Cluaupp/) · [Learn](https://kartzrbx.github.io/Cluaupp/learn/) · [API](https://kartzrbx.github.io/Cluaupp/api/classes/)
9
+ [Docs](https://kartzrbx.github.io/Cluaupp/) · [Handbook](https://kartzrbx.github.io/Cluaupp/docs/)
10
10
 
11
11
  [![npm version](https://img.shields.io/npm/v/cluaupp.svg)](https://www.npmjs.com/package/cluaupp)
12
12
  [![Node.js](https://img.shields.io/node/v/cluaupp.svg)](https://nodejs.org)
package/docs/README.md CHANGED
@@ -1,23 +1,35 @@
1
1
  # Cluaupp documentation
2
2
 
3
+ The live handbook is **[GitHub Pages](https://kartzrbx.github.io/Cluaupp/docs/)** — every construct the CLI accepts, not an Enum dump.
4
+
5
+ ## Start
6
+
3
7
  1. [Intro](intro.md) — what Cluaupp is
4
- 2. [Getting started](getting-started.md) — npm, Rojo, Wally
5
- 3. [CLI](cli.md) — `init`, `build`, `watch`
6
- 4. [Syntax](syntax.md) — C++ subset, `local`, `const`
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
20
-
21
- Moonwave site (local): `npx moonwave dev`
22
-
23
- Full site + engine API: **[GitHub Pages](https://kartzrbx.github.io/Cluaupp/)**
8
+ 2. [Getting started](getting-started.md) — npm, `init`, Rojo, clangd
9
+ 3. [CLI](cli.md) — `init`, `build`, `watch`, `lsp`, `intellisense`, flags
10
+ 4. [Config](config.md) — `cluaupp.config.json`
11
+ 5. [IntelliSense](intellisense.md) — clangd only
12
+
13
+ ## Language
14
+
15
+ 6. [Syntax](syntax.md) — **complete subset**: files, types, functions, scopes, control, operators, strings, `string_concat`, callbacks, casts, OOP, singletons, unsupported
16
+ 7. [print and cout](print-cout.md) — logging
17
+ 8. [C++ types](cpp-types.md) — primitives, Instances, `LuaArray`
18
+ 9. [const](cpp-const.md) — immutability
19
+ 10. [Advanced](cpp-advanced.md) — `::` vs `:`, Wally, optimization notes
20
+
21
+ ## Structure
22
+
23
+ 11. [Organization](cpp-organization.md) — server / client / shared, filename tags
24
+ 12. [Architecture](architecture.md) — one file in, one file out
25
+ 13. [OOP structure](oop/index.md) — structs, sibling headers, `Class::` methods, singletons
26
+ 14. [Safety](cpp-safety.md) — client trust, Janitor, Net, DataService
27
+
28
+ ## Roblox
29
+
30
+ 15. [Libraries](libraries/index.md) — DataService, Janitor, Fusion / Iris / UI
31
+ 16. [Examples](examples/index.md) — leaderstats, combat, shop, HUD
32
+ 17. [Roblox API](roblox-api.md) — how to spell engine calls (Creator Hub for members)
33
+ 18. [Comparison](comparison.md) — roblox-ts and WASM
34
+
35
+ Moonwave (local): `npx moonwave dev`. Site rebuild: `npm run site`.
package/docs/cli.md CHANGED
@@ -60,7 +60,7 @@ Stdio JSON-RPC for **Cluaupp subset diagnostics** only. Completion, hover, and d
60
60
 
61
61
  ## `cluaupp intellisense [folder]`
62
62
 
63
- Writes `compile_commands.json`, `.clangd`, and `.vscode` for clangd, and installs LLVM clangd when needed.
63
+ Alias: `intelisense`. Writes `compile_commands.json`, `.clangd`, and `.vscode` for clangd, and installs LLVM clangd when needed.
64
64
 
65
65
  ## `cluaupp --version` / `cluaupp -v`
66
66
 
@@ -10,15 +10,18 @@ The subset is intentional. What exists is enough for game scripts; what is missi
10
10
  ## Supported
11
11
 
12
12
  - Functions, prototypes (headers only), `if` / `else` / `while` / range-`for` / `switch` (`case`, `default`, `break`)
13
+ - `struct` types + `Class::` methods in a sibling `.h` / `.cpp`
13
14
  - `new Class(parent)`, `GetService<T>()`, `::` statics (`CFrame::lookAt`, `Enum::Material::Plastic`)
15
+ - `static_cast<T>(x)`, `(void)x`, lambdas in `Connect` / `Add`
16
+ - `static` / `constexpr` / `inline` specifiers, `LuaArray<T>`, `string_concat`
14
17
  - `->` methods and properties, `.` members, `Connect`
15
- - `const`, `auto`, `nullptr`, arithmetic, `&&` `||` `!=`
18
+ - `const`, `auto`, `nullptr`, arithmetic, `&&` `||` `!=`, string `+`
16
19
  - Quoted includes, `.h` / `.hpp` as sources
17
20
  - Libraries via `#include <cluaupp/libs/...>` → `require(CluauppLibs.*)`
18
21
 
19
22
  ## Not supported (yet)
20
23
 
21
- Full C++: templates besides `GetService<T>`, `class` bodies as emitted types, `std::`, overloading as two runtimes, C-style `for`, macros, pointer arithmetic.
24
+ Full C++: templates besides `GetService<T>` / `static_cast` / `LuaArray`, `class` bodies as emitted metatables, `std::`, overloading as two runtimes, C-style `for`, macros, pointer arithmetic, JSX.
22
25
 
23
26
  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
27
 
@@ -72,4 +75,4 @@ void Grant(Player* player, int amount) {
72
75
  5. **Headers declare, scripts define.** Prototypes in `.h`, bodies in `.cpp`.
73
76
  6. **Do not share mutable statics across server and client** — use Net or DataService.
74
77
 
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).
78
+ See also: [syntax](syntax.md) (complete subset), [print and cout](print-cout.md), [libraries](libraries/index.md), [OOP](oop/index.md), [examples](examples/index.md), [comparison](comparison.md). Optimization notes on the site: [Optimization](https://kartzrbx.github.io/Cluaupp/docs/optimization.html).
package/docs/cpp-types.md CHANGED
@@ -17,6 +17,8 @@ Cluaupp is statically typed in the C++ you write and in the Luau it emits. A typ
17
17
  | `void` | (no return) | procedures |
18
18
  | `auto` | inferred | when `new` or `GetService` makes the type obvious |
19
19
  | `Player*`, `Folder*`, … | `Player`, `Folder` | Instances |
20
+ | `LuaArray<int>` / `vector<T>` | `{number}` | arrays (Template inventory, `GetPlayers`) |
21
+ | `optional<T>` | `T?` | missing values (prefer `nullptr` on Instances) |
20
22
  | `Vector3`, `CFrame`, `UDim2` | same | datatypes |
21
23
 
22
24
  ```cpp
@@ -9,7 +9,7 @@ Client-only: wait for the replicated profile, write labels, listen for currency
9
9
 
10
10
  Put a ScreenGui named `Hud` in StarterGui with `MoneyLabel` and `LevelLabel` (`TextLabel`).
11
11
 
12
- Define callbacks **above** `init()` so clangd and the subset both see them (no lambdas).
12
+ Define callbacks **above** `init()` or use lambdas in `Connect`.
13
13
 
14
14
  ## `HudClient.client.cpp`
15
15
 
@@ -9,7 +9,7 @@ High-quality Cluaupp systems you can copy. Each page is a full service: C++ that
9
9
 
10
10
  In this repo the live sample is [`examples/game`](../../examples/game) (`src/server`, `src/client`, `src/shared`). Compiler TypeScript is never mixed with game C++. `cluaupp init` still copies [`templates/game`](../../templates/game).
11
11
 
12
- These are **not** dumps of `int main()`. Entry is `void init()`. There are no lambdas and no custom C++ classes — named functions + structs.
12
+ These are **not** dumps of `int main()`. Entry is `void init()`. Types are `struct` + `Class::` methods. Callbacks may be named functions or lambdas. Canonical Leaderstats: [handbook](https://kartzrbx.github.io/Cluaupp/docs/leaderstats.html).
13
13
 
14
14
  ## Suggested layout
15
15
 
@@ -5,136 +5,65 @@ sidebar_position: 3
5
5
 
6
6
  # Leaderstats
7
7
 
8
- Roblox shows the player list from a Folder named exactly `leaderstats` under the Player, with `IntValue` / `StringValue` children. This service **creates** those values, then mirrors DataService currencies into them.
8
+ Canonical copy (three files): [Docs → Example: Leaderstats](https://kartzrbx.github.io/Cluaupp/docs/leaderstats.html).
9
9
 
10
- It does **not** call `DataService.Init`. Boot that in [Data boot](data-boot.md).
10
+ Roblox shows the player list from a Folder named exactly `leaderstats` under the Player. This service **creates** those values, then mirrors DataService coins into them.
11
11
 
12
- ## Why this shape
12
+ It does **not** call `DataService.Init`. Boot that in [Data boot](data-boot.md) with your `PlayerData` Template.
13
+
14
+ ## Files
15
+
16
+ | File | Role |
17
+ | --- | --- |
18
+ | `shared/PlayerData.h` | Template structs (`Currencies.Coins`, inventory `LuaArray`) |
19
+ | `server/LeaderstatsServer.h` | `struct LeaderstatsServer` — fields + method decls (same stem) |
20
+ | `server/LeaderstatsServer.server.cpp` | `Class::` bodies + `void init()` |
21
+
22
+ ## Rules
13
23
 
14
24
  | Rule | Why |
15
25
  | --- | --- |
16
- | Create the Folder if missing | `FindFirstChild` is not a constructor |
17
- | Create the stat if missing | Returning early when it is absent never shows Money |
18
- | `StringValue` + `FormatNumber::Abbreviate` | Player list wants a string like `1.5K` |
19
- | Janitor per player, keyed by `player->Name` | Leaving the game must `Destroy` the section janitor |
20
- | `GetChangedSignal(Paths.Currencies)` | HUD / list update without polling |
21
- | Named function, not a lambda | Cluaupp has no lambdas. The shared callback refreshes **all** players (currency writes are rare) |
26
+ | Same-stem header | `LeaderstatsServer.h` + `LeaderstatsServer.server.cpp`. A differently named `leaderstats.h` is a `require`. |
27
+ | `.server.cpp` | Untagged cpp is a ModuleScript; `init()` will not run by itself. |
28
+ | `Paths.Currencies.Coins` | After `Init`. A local `int Coins` is not a Data path. |
29
+ | `string_concat` or string `+` | Luau `..`. Do not write `..` in the `.cpp`. |
30
+ | Janitor keyed by player name | Leaving the game must `Destroy` the folder. |
31
+ | Lambda or named function | `GetChangedSignal(...).Connect([coinsValue](int n) { ... })` is valid. |
22
32
 
23
- ## `LeaderstatsServer.server.cpp`
33
+ ## Header
24
34
 
25
35
  ```cpp
36
+ #pragma once
26
37
  #include <cluaupp/roblox.hpp>
27
38
  #include <cluaupp/libs/janitor.hpp>
28
39
  #include <cluaupp/libs/dataservice.hpp>
29
- #include <cluaupp/libs/formatnumber.hpp>
30
-
31
- Players* Players = GetService<Players>();
32
- Janitor* janitor = new Janitor();
33
-
34
- void EnsureStat(Folder* leaderstats, string name) {
35
- Instance* existing = leaderstats->FindFirstChild(name);
36
- if (existing != nullptr) {
37
- return;
38
- }
39
- StringValue* stat = new StringValue(leaderstats);
40
- stat->Name = name;
41
- stat->Value = "0";
42
- }
43
-
44
- void SetStat(Folder* leaderstats, string name, int value) {
45
- StringValue* stat = leaderstats->FindFirstChild(name);
46
- if (stat == nullptr) {
47
- cout::warn << "leaderstats missing " << name << endl;
48
- return;
49
- }
50
- stat->Value = FormatNumber::Abbreviate(value);
51
- }
52
-
53
- Folder* EnsureLeaderstats(Player* player) {
54
- Folder* leaderstats = player->FindFirstChild("leaderstats");
55
- if (leaderstats != nullptr) {
56
- return leaderstats;
57
- }
58
- leaderstats = new Folder(player);
59
- leaderstats->Name = "leaderstats";
60
- return leaderstats;
61
- }
62
-
63
- void ApplyCurrencies(Player* player) {
64
- Data* data = DataService::Server.Get(player);
65
- if (data == nullptr) {
66
- return;
67
- }
68
- Folder* leaderstats = player->FindFirstChild("leaderstats");
69
- if (leaderstats == nullptr) {
70
- return;
71
- }
72
- int money = data->Get(DataService::Server.Paths.Currencies.Money);
73
- int level = data->Get(DataService::Server.Paths.Currencies.Level);
74
- SetStat(leaderstats, "Money", money);
75
- SetStat(leaderstats, "Level", level);
76
- }
77
-
78
- void OnCurrenciesChanged() {
79
- for (Player* player : Players->GetPlayers()) {
80
- ApplyCurrencies(player);
81
- }
82
- }
83
-
84
- void SetupPlayer(Player* player) {
85
- Data* data = DataService::Server.WaitFor(player);
86
- if (data == nullptr) {
87
- cout::warn << "no profile for " << player->Name << endl;
88
- return;
89
- }
90
-
91
- Folder* leaderstats = EnsureLeaderstats(player);
92
- EnsureStat(leaderstats, "Money");
93
- EnsureStat(leaderstats, "Level");
94
- ApplyCurrencies(player);
95
40
 
96
- Janitor* section = new Janitor();
97
- section->Add(data->GetChangedSignal(DataService::Server.Paths.Currencies).Connect(OnCurrenciesChanged));
98
- section->Add(leaderstats, "Destroy");
99
- janitor->Add(section, "Destroy", player->Name);
100
- }
41
+ struct LeaderstatsServer {
42
+ static constexpr int STARTING_COINS = 0;
43
+ Janitor* janitor;
44
+ string GetPlayerJanitorKey(Player* player);
45
+ void UpdateLeaderstatsWithValues(IntValue* currentValue, int newValue);
46
+ Folder* EnsurePlayerLeaderstatsFolder(Player* player);
47
+ void PlayerEntered(Player* player);
48
+ };
49
+ ```
101
50
 
102
- void OnPlayerRemoving(Player* player) {
103
- if (janitor->Get(player->Name)) {
104
- janitor->Remove(player->Name);
105
- }
106
- }
51
+ ## `PlayerEntered`
107
52
 
108
- void OnClose() {
109
- janitor->Destroy();
110
- }
111
-
112
- void init() {
113
- for (Player* player : Players->GetPlayers()) {
114
- SetupPlayer(player);
53
+ ```cpp
54
+ void LeaderstatsServer::PlayerEntered(Player* player) {
55
+ Folder* leaderstatsFolder = EnsurePlayerLeaderstatsFolder(player);
56
+ Data* playerData = DataService::Server.WaitFor(player);
57
+ IntValue* coinsValue = static_cast<IntValue*>(leaderstatsFolder->FindFirstChild("Coins"));
58
+ if (coinsValue) {
59
+ playerData->GetChangedSignal(DataService::Server.Paths.Currencies.Coins).Connect(
60
+ [coinsValue](int newValue) {
61
+ UpdateLeaderstatsWithValues(coinsValue, newValue);
62
+ }
63
+ );
115
64
  }
116
- janitor->Add(Players->PlayerAdded.Connect(SetupPlayer));
117
- janitor->Add(Players->PlayerRemoving.Connect(OnPlayerRemoving));
118
- game->BindToClose(OnClose);
65
+ janitor->Add(leaderstatsFolder, "Destroy", GetPlayerJanitorKey(player));
119
66
  }
120
67
  ```
121
68
 
122
- ## Output
123
-
124
- `LeaderstatsServer.server.cpp` becomes a service folder: `init.luau` (Script, RunContext **Server**), `Main`, `PlayersManager`, `DataController` / `CacheController`, Types. Your functions stay in the domain controller. See [services](../oop/services.md).
125
-
126
- ## Bugs this example avoids
127
-
128
- | Broken | Correct |
129
- | --- | --- |
130
- | `if (!existing) { return; }` then never create the value | `EnsureStat` **creates** when missing |
131
- | `if (!money) { money->Value = ... }` | That writes only when the child is **nil** (crash / no-op). Set when the child **exists** |
132
- | `DataService.Get` before `WaitFor` on join | `WaitFor` in `SetupPlayer`, `Get` in the refresh path |
133
- | `int main()` | `void init()` |
134
- | One global connection, never removed | Section janitor destroyed on `PlayerRemoving` |
135
-
136
- `Paths.Currencies` is valid **after** your Template was passed to `Init`. The library header does not define those fields.
137
-
138
- ## IntValue vs StringValue
139
-
140
- Use `IntValue` if you want the default numeric sort and no abbreviation. Use `StringValue` + `FormatNumber::Abbreviate` for `1.5K`. Do not mix both names (`Money` twice).
69
+ `init()` constructs `LeaderstatsServer`, assigns `janitor = new Janitor()`, runs `PlayerEntered` for everyone already in the game, then `PlayerAdded` + `BindToClose`. Full listing is on the [handbook page](https://kartzrbx.github.io/Cluaupp/docs/leaderstats.html).
@@ -93,7 +93,7 @@ void init() {
93
93
 
94
94
  This becomes `Vector3.new`, `CFrame.lookAt`, `Color3.fromRGB`, `UDim2.fromScale`, `Enum.Material.Plastic`.
95
95
 
96
- Full reference (every class from [create.roblox.com](https://create.roblox.com/docs/reference/engine)): [Cluaupp GitHub Pages](https://kartzrbx.github.io/Cluaupp/).
96
+ How to spell engine calls: [Roblox in Cluaupp](https://kartzrbx.github.io/Cluaupp/docs/engine.html). Official members: [create.roblox.com](https://create.roblox.com/docs/reference/engine). The complete subset: [Language reference](https://kartzrbx.github.io/Cluaupp/docs/reference.html).
97
97
 
98
98
  ## How to write
99
99
 
@@ -130,7 +130,7 @@ If a file defines `void init()`, Cluaupp calls `init()` at the end of the `.luau
130
130
  cluaupp intellisense
131
131
  ```
132
132
 
133
- `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is **not** compiled to Luau. clangd learns that path from `-Iinclude` in `.clangd`, `compile_flags.txt`, and `compile_commands.json` — it does not read `c_cpp_properties.json`.
133
+ `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is **not** compiled to Luau. clangd learns that path from `-Iinclude` in `.clangd`, `compile_flags.txt`, and `compile_commands.json`.
134
134
 
135
135
  See [IntelliSense](intellisense.md).
136
136
 
@@ -163,6 +163,8 @@ See [Libraries](libraries/index.md), [OOP](oop/index.md), [types](cpp-types.md),
163
163
 
164
164
  ## Next
165
165
 
166
+ Language handbook (GitHub Pages): **[Docs](https://kartzrbx.github.io/Cluaupp/docs/)** — [every construct](https://kartzrbx.github.io/Cluaupp/docs/reference.html).
167
+
166
168
  - [C++ → Luau syntax](syntax.md)
167
169
  - [print and cout](print-cout.md)
168
170
  - [C++ types](cpp-types.md)
@@ -6,12 +6,12 @@ C++ completion, hover, and go-to-definition are **clangd**. Cluaupp does not shi
6
6
 
7
7
  1. [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) (`llvm-vs-code-extensions.vscode-clangd`)
8
8
  2. LLVM `clang++` when missing (Windows: `winget install --id LLVM.LLVM -e`)
9
- 3. `.clangd`, `compile_flags.txt`, and `compile_commands.json` so clangd finds `include/` (clangd does **not** read `.vscode/c_cpp_properties.json`)
9
+ 3. `.clangd`, `compile_flags.txt`, and `compile_commands.json` so clangd finds `include/`
10
10
  4. Forced include of `include/cluaupp/roblox.hpp` so `GetService`, `Player`, `Janitor` complete from the real C++ stubs
11
11
 
12
12
  Tree-sitter is the **compiler** frontend (collect → emit Luau). It is not an editor language server. A homemade tokenizer in the CLI would fight clangd — that path is gone.
13
13
 
14
- Microsoft `ms-vscode.cpptools` is **not** used. Two C++ engines in the same window fight; Cluaupp disables the Microsoft engine (`C_Cpp.intelliSenseEngine: Disabled`).
14
+ Microsoft `ms-vscode.cpptools` is **not** used and is **not licensed for Cursor**. Two C++ engines in the same window fight; Cluaupp recommends only clangd and marks cpptools as unwanted.
15
15
 
16
16
  `cluaupp lsp` only publishes **subset parse errors** (code that clangd may accept as C++ but Cluaupp will not transpile).
17
17
 
@@ -39,9 +39,8 @@ Reload: Command Palette → **Developer: Reload Window**. clangd should attach t
39
39
 
40
40
  | File | Role |
41
41
  | --- | --- |
42
- | `.vscode/c_cpp_properties.json` | compiler path (unused by clangd; kept if someone re-enables cpptools) |
43
- | `.vscode/settings.json` | `C_Cpp.intelliSenseEngine: Disabled`, `clangd.enable: true`, `--compile-commands-dir` |
44
- | `.vscode/extensions.json` | recommends `llvm-vs-code-extensions.vscode-clangd` |
42
+ | `.vscode/settings.json` | `clangd.enable: true`, `--compile-commands-dir` |
43
+ | `.vscode/extensions.json` | recommends `llvm-vs-code-extensions.vscode-clangd`; marks `ms-vscode.cpptools` unwanted |
45
44
  | `.clangd` | C++20, `-Iinclude`, skip `out/` and `libs/` |
46
45
  | `compile_flags.txt` | fallback flags if a file is not yet in `compile_commands.json` |
47
46
  | `compile_commands.json` | one entry per `src/` file |
@@ -91,9 +91,12 @@ void OnCurrenciesChanged() {
91
91
  }
92
92
 
93
93
  data->GetChangedSignal(DataService::Server.Paths.Currencies).Connect(OnCurrenciesChanged);
94
+ data->GetChangedSignal(DataService::Server.Paths.Currencies.Coins).Connect([](int coins) {
95
+ print(coins);
96
+ });
94
97
  ```
95
98
 
96
- `GetChangedSignal` fires when that path (or a child) changes. Cluaupp has no lambdas — use a named function.
99
+ `GetChangedSignal` fires when that path (or a child) changes. Use a named function or a lambda (`[](int newValue) { ... }`).
97
100
 
98
101
  ## Rules
99
102
 
@@ -13,7 +13,8 @@ sidebar_position: 1
13
13
  | [Janitor](janitor.md) | Connections, instances, cleanup on leave |
14
14
  | [Promise](promise.md) | Delay, Then / Catch / Await |
15
15
  | [Net](net.md) | RemoteEvent / RemoteFunction without making remotes |
16
- | [More libraries](more.md) | FormatNumber, Fusion, Cmdr, Twinkle, MathUtils, … |
16
+ | [Declarative UI](ui.md) | Fusion, Iris, Vide, React/Roact — no JSX |
17
+ | [More libraries](more.md) | FormatNumber, Twinkle, TopbarPlus, EzVisualz, … |
17
18
 
18
19
  Sources: [runtime/SOURCES.md](https://github.com/KartzRbx/Cluaupp/blob/main/runtime/SOURCES.md). Re-vendor: `node scripts/vendor-libs.js`.
19
20
 
@@ -60,7 +60,9 @@ billboard->SetText("Hello");
60
60
 
61
61
  ## Fusion / Iris / Cmdr / TopbarPlus / Chrono / EzVisualz / StateMachine / Spring / Display
62
62
 
63
- These are the GitHub systems behind typed `init.luau` borders. Include the matching `<cluaupp/libs/*.hpp>` and call the same names as the upstream README. Cluaupp does not re-document every Fusion `Value` / Cmdr command — use:
63
+ Cluaupp has **no JSX**. Declarative UI is function calls. First-party: Fusion (reactive) and Iris (immediate-mode debug). Vide and Roact/React use the same C++ spelling (`createElement` / `source`), not `<frame />`. Handbook: [Declarative UI](https://kartzrbx.github.io/Cluaupp/docs/ui.html).
64
+
65
+ Include the matching `<cluaupp/libs/*.hpp>` and call the same names as the upstream README:
64
66
 
65
67
  | Lib | Header | Upstream |
66
68
  | --- | --- | --- |
@@ -0,0 +1,76 @@
1
+ ---
2
+ title: Declarative UI
3
+ sidebar_position: 5
4
+ ---
5
+
6
+ # Declarative UI
7
+
8
+ Live handbook (examples, C++ / Luau tabs): **[Declarative UI](https://kartzrbx.github.io/Cluaupp/docs/ui.html)**.
9
+
10
+ roblox-ts can compile [Roact JSX](https://roblox-ts.com/docs/guides/roact-jsx) because TypeScript has JSX. **Cluaupp does not.** There are no `<frame />` tags. You call the library the way Luau does: functions, designated-initializer tables, lambdas.
11
+
12
+ ## Pick a model
13
+
14
+ | When you want… | Use | In Cluaupp |
15
+ | --- | --- | --- |
16
+ | A few labels you set by hand | Imperative Instances | `new TextLabel(gui)` |
17
+ | UI that follows state | [Fusion](https://github.com/dphfox/Fusion) | Shipped: `#include <cluaupp/libs/fusion.hpp>` |
18
+ | The same idea, sources | [Vide](https://github.com/centau/vide) | Not shipped — calling convention on the handbook |
19
+ | A virtual tree | Roact / [jsdotlua React](https://github.com/jsdotlua/react) | Not shipped — `createElement`, never JSX |
20
+ | Studio debug panels | [Iris](https://github.com/SirMallard/Iris) | Shipped: `#include <cluaupp/libs/iris.hpp>` |
21
+ | Topbar / fade / rainbow | TopbarPlus, Twinkle, EzVisualz | Shipped — polish Instances you already have |
22
+
23
+ Fusion and Iris are in CluauppLibs. Vide and React/Roact are **not** vendored.
24
+
25
+ ## JSX → Cluaupp
26
+
27
+ | roblox-ts JSX | Cluaupp |
28
+ | --- | --- |
29
+ | `<frame Size={u} />` | `React::createElement("Frame", { .Size = u })` |
30
+ | `<textlabel Key="Coins" />` | `.Key = "Coins"` on the props table |
31
+ | `Event={{ Activated: fn }}` | `.Event = { .Activated = fn }` |
32
+ | `<MyButton text="Buy" />` | `React::createElement(MyButton, { .text = "Buy" })` |
33
+
34
+ ## Fusion (shipped)
35
+
36
+ ```cpp
37
+ #include <cluaupp/libs/fusion.hpp>
38
+
39
+ FusionScope scope = Fusion::scoped();
40
+ FusionState coins = Fusion::Value(0);
41
+ Fusion::New("TextLabel")({
42
+ .Name = "Coins",
43
+ .Parent = gui,
44
+ .Size = UDim2::fromScale(1, 0.1),
45
+ });
46
+ ```
47
+
48
+ Wire `coins(newValue)` from `DataService::Client` `GetChangedSignal(Paths.Currencies.Coins)`. Use `Computed` for strings, `Hydrate` for a ScreenGui that already exists in Studio, `Spring` / `Tween` for motion.
49
+
50
+ ## Vide / React
51
+
52
+ Same subset: **no JSX**. Vide is `source` / `derive` / `create("TextLabel")({ .Parent = gui })`. React is `createElement("Frame", { .Key = "Child" }, child)` plus `Key`, `Ref`, `Change`, `Event` as table fields. Full copies with C++ / Luau tabs: the [handbook page](https://kartzrbx.github.io/Cluaupp/docs/ui.html).
53
+
54
+ ## Iris (shipped, debug only)
55
+
56
+ ```cpp
57
+ #include <cluaupp/libs/iris.hpp>
58
+
59
+ void DrawEconomy() {
60
+ if (Iris::Window("Economy")) {
61
+ Iris::Text("Coins");
62
+ Iris::End();
63
+ }
64
+ }
65
+
66
+ void init() {
67
+ Iris::Init();
68
+ Iris::Connect(DrawEconomy);
69
+ }
70
+ ```
71
+
72
+ Do not use Iris as the live player HUD. Pair every `Window` / `Tree` with `End()`.
73
+
74
+ ## One owner per ScreenGui
75
+
76
+ Do not mount Fusion and React on the same gui. Twinkle / TopbarPlus / EzVisualz can decorate that owner’s Instances. Client code must not `Set` persisted DataService paths.
package/docs/oop/index.md CHANGED
@@ -3,15 +3,28 @@ title: OOP structure
3
3
  sidebar_position: 1
4
4
  ---
5
5
 
6
- # OOP structure
6
+ # Structs and methods
7
7
 
8
- The **live site** (not just these markdown files) is GitHub Pages:
8
+ Live handbook: [Structs and methods](https://kartzrbx.github.io/Cluaupp/docs/structs.html). Singletons: [one table in `init()`](https://kartzrbx.github.io/Cluaupp/docs/singletons.html).
9
9
 
10
- - [Learn → OOP structure](https://kartzrbx.github.io/Cluaupp/learn/index.html)
11
- - [Guide → OOP](https://kartzrbx.github.io/Cluaupp/guide/oop.html)
12
- - [Examples](https://kartzrbx.github.io/Cluaupp/guide/examples.html)
10
+ Cluaupp does **not** emit C++ `class` metatables. You write a **type** as a `struct` in a sibling header and implement `Class::Method` in the `.cpp`. Filename tags still decide Script / LocalScript / ModuleScript.
13
11
 
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`).
12
+ Construct **one** `LeaderstatsServer` in `void init()`, assign `janitor = new Janitor()`, and capture it in `[&]` lambdas. Library singletons already exist (`DataService::Server`) — `Init` once from a boot script. Join strings with `string_concat` or string `+`, not Luau `..`.
13
+
14
+ ```cpp
15
+ #pragma once
16
+ #include <cluaupp/roblox.hpp>
17
+ #include <cluaupp/libs/janitor.hpp>
18
+
19
+ struct LeaderstatsServer {
20
+ static constexpr int STARTING_COINS = 0;
21
+ Janitor* janitor;
22
+ string GetPlayerJanitorKey(Player* player);
23
+ void PlayerEntered(Player* player);
24
+ };
25
+ ```
26
+
27
+ The stem must match: `LeaderstatsServer.h` next to `LeaderstatsServer.server.cpp`. `#include "leaderstats.h"` from a differently named cpp is a `require`, not the class body.
15
28
 
16
29
  | Page | What you learn |
17
30
  | --- | --- |
@@ -19,4 +32,4 @@ Cluaupp does **not** compile custom C++ `class` types yet. “OOP” here is how
19
32
  | [Services](services.md) | One `.server.cpp` → one `.server.luau` |
20
33
  | [Modules](modules.md) | Untagged files, structs, named functions as methods |
21
34
 
22
- Planner details: [Architecture](../architecture.md). Folder layout: [Organization](../cpp-organization.md). Full services: [Examples](../examples/index.md).
35
+ Planner: [Architecture](../architecture.md). Folder layout: [Organization](../cpp-organization.md). Full copy: [Leaderstats](../examples/leaderstats.md).
@@ -1,16 +1,10 @@
1
1
  # Roblox API
2
2
 
3
- Cluaupp covers the engine API listed on [create.roblox.com](https://create.roblox.com/docs/reference/engine): **925 classes**, **636 enums**, and the datatypes (`Vector3`, `CFrame`, `UDim`, `UDim2`, …).
3
+ Cluaupp uses the official engine. Spell the call in C++; look up members on [create.roblox.com](https://create.roblox.com/docs/reference/engine). The GitHub Pages site is a **language handbook**, not a dump of every Enum item.
4
4
 
5
- The **page-by-page** reference (every property, method, and event, with C++ and Luau) lives on the generated site:
5
+ Handbook: **[Docs](https://kartzrbx.github.io/Cluaupp/docs/)** · [Roblox in Cluaupp](https://kartzrbx.github.io/Cluaupp/docs/engine.html)
6
6
 
7
- **[Cluaupp docs (GitHub Pages)](https://kartzrbx.github.io/Cluaupp/)**
8
-
9
- - [Datatypes](https://kartzrbx.github.io/Cluaupp/api/datatypes/)
10
- - [Classes](https://kartzrbx.github.io/Cluaupp/api/classes/)
11
- - [Enums](https://kartzrbx.github.io/Cluaupp/api/enums/)
12
-
13
- In C++, `#include <cluaupp/roblox.hpp>`. The compiler ignores the header and emits real Luau.
7
+ `#include <cluaupp/roblox.hpp>` is IntelliSense. The compiler ignores the header and emits real Luau.
14
8
 
15
9
  ## Datatypes
16
10
 
@@ -20,7 +14,6 @@ part->Position = Vector3(0, 10, 0);
20
14
  part->CFrame = CFrame::lookAt(Vector3(0, 10, 0), Vector3(0, 10, -10));
21
15
  part->Color = Color3::fromRGB(255, 0, 0);
22
16
  frame->Size = UDim2::fromScale(1, 1);
23
- frame->Position = UDim2(0, 0, 0.5, 0);
24
17
  auto material = Enum::Material::Plastic;
25
18
  ```
26
19
 
@@ -30,52 +23,7 @@ part.Position = Vector3.new(0, 10, 0)
30
23
  part.CFrame = CFrame.lookAt(Vector3.new(0, 10, 0), Vector3.new(0, 10, -10))
31
24
  part.Color = Color3.fromRGB(255, 0, 0)
32
25
  frame.Size = UDim2.fromScale(1, 1)
33
- frame.Position = UDim2.new(0, 0, 0.5, 0)
34
26
  local material = Enum.Material.Plastic
35
27
  ```
36
28
 
37
- | C++ | Luau |
38
- | --- | --- |
39
- | `Vector3(x, y, z)` | `Vector3.new(x, y, z)` |
40
- | `Vector2(x, y)` | `Vector2.new(x, y)` |
41
- | `CFrame(x, y, z)` | `CFrame.new(x, y, z)` |
42
- | `CFrame::lookAt(from, look)` | `CFrame.lookAt(from, look)` |
43
- | `UDim(scale, offset)` | `UDim.new(scale, offset)` |
44
- | `UDim2(xs, xo, ys, yo)` | `UDim2.new(xs, xo, ys, yo)` |
45
- | `UDim2::fromScale(x, y)` | `UDim2.fromScale(x, y)` |
46
- | `UDim2::fromOffset(x, y)` | `UDim2.fromOffset(x, y)` |
47
- | `Color3::fromRGB(r, g, b)` | `Color3.fromRGB(r, g, b)` |
48
- | `Color3::fromHSV(h, s, v)` | `Color3.fromHSV(h, s, v)` |
49
- | `BrickColor("Bright red")` | `BrickColor.new("Bright red")` |
50
- | `Enum::Material::Plastic` | `Enum.Material.Plastic` |
51
- | `Rect(x0, y0, x1, y1)` | `Rect.new(x0, y0, x1, y1)` |
52
- | `Ray(origin, direction)` | `Ray.new(origin, direction)` |
53
- | `NumberRange(min, max)` | `NumberRange.new(min, max)` |
54
- | `TweenInfo(time, style)` | `TweenInfo.new(time, style)` |
55
-
56
- ## Instances and services
57
-
58
- ```cpp
59
- auto* part = new Part(workspace);
60
- auto* players = GetService<Players>();
61
- player->FindFirstChild("leaderstats");
62
- players->GetPlayers();
63
- ```
64
-
65
- ```luau
66
- local part: Part = Instance.new("Part")
67
- part.Parent = workspace
68
- local players: Players = game:GetService("Players")
69
- player:FindFirstChild("leaderstats")
70
- players:GetPlayers()
71
- ```
72
-
73
- `new Class(parent)` is for creatable classes (`Instance.new`). Services use `GetService<Name>()`.
74
-
75
- Generated headers (official client dump):
76
-
77
- - `include/cluaupp/datatypes.hpp`
78
- - `include/cluaupp/generated/enums.hpp`
79
- - `include/cluaupp/generated/instances.hpp`
80
-
81
- To regenerate: `npm run generate-api` in the `cluau/` folder.
29
+ Every enum is `Enum::Name::Item` → `Enum.Name.Item`. Services are `GetService<Players>()`. Instances are `new Folder(parent)` and `player->FindFirstChild("x")`.