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
@@ -0,0 +1,122 @@
1
+ ---
2
+ title: Shop
3
+ sidebar_position: 5
4
+ ---
5
+
6
+ # Shop
7
+
8
+ The client sends **which product**. The server looks up the price, checks Money, then `Set`. Never let the client send the new balance or the price.
9
+
10
+ ## Catalog header
11
+
12
+ `src/shared/constants/ShopCatalog.hpp`
13
+
14
+ Cluaupp has no maps. A function with early returns is the catalog.
15
+
16
+ ```cpp
17
+ #pragma once
18
+
19
+ const int PRODUCT_HEALTH_PACK = 1;
20
+ const int PRODUCT_SPEED_TOME = 2;
21
+
22
+ int PriceOf(int productId) {
23
+ if (productId == PRODUCT_HEALTH_PACK) {
24
+ return 50;
25
+ }
26
+ if (productId == PRODUCT_SPEED_TOME) {
27
+ return 200;
28
+ }
29
+ return 0;
30
+ }
31
+ ```
32
+
33
+ `PriceOf` lives in a header so the **server** is the copy that matters. The client may include it for UI labels, but a patched client cannot change what the server charges.
34
+
35
+ ## Server — `ShopServer.server.cpp`
36
+
37
+ ```cpp
38
+ #include <cluaupp/roblox.hpp>
39
+ #include <cluaupp/libs/janitor.hpp>
40
+ #include <cluaupp/libs/net.hpp>
41
+ #include <cluaupp/libs/dataservice.hpp>
42
+ #include "../../../shared/constants/ShopCatalog.hpp"
43
+
44
+ Janitor* janitor = new Janitor();
45
+ NetEvent* Buy = Net::Event("Buy");
46
+
47
+ void ApplyProduct(Player* player, int productId) {
48
+ Model* character = player->Character;
49
+ if (character == nullptr) {
50
+ return;
51
+ }
52
+ Humanoid* humanoid = character->FindFirstChildOfClass("Humanoid");
53
+ if (humanoid == nullptr) {
54
+ return;
55
+ }
56
+ if (productId == PRODUCT_HEALTH_PACK) {
57
+ humanoid->Health = humanoid->MaxHealth;
58
+ return;
59
+ }
60
+ if (productId == PRODUCT_SPEED_TOME) {
61
+ humanoid->WalkSpeed = 24;
62
+ return;
63
+ }
64
+ }
65
+
66
+ void OnBuy(Player* player, int productId) {
67
+ int price = PriceOf(productId);
68
+ if (price < 1) {
69
+ cout::warn << "unknown product " << productId << endl;
70
+ return;
71
+ }
72
+ Data* data = DataService::Server.WaitFor(player);
73
+ if (data == nullptr) {
74
+ return;
75
+ }
76
+ int money = data->Get(DataService::Server.Paths.Currencies.Money);
77
+ if (money < price) {
78
+ cout::ping << player->Name << " cannot afford " << productId << endl;
79
+ return;
80
+ }
81
+ data->Set(DataService::Server.Paths.Currencies.Money, money - price);
82
+ ApplyProduct(player, productId);
83
+ }
84
+
85
+ void init() {
86
+ Buy->On(OnBuy);
87
+ janitor->Add(Buy);
88
+ }
89
+ ```
90
+
91
+ Debit **before** (or atomically with) the effect. If you grant the item first and the `Set` fails, the player dupes.
92
+
93
+ ## Client — `ShopClient.client.cpp`
94
+
95
+ ```cpp
96
+ #include <cluaupp/roblox.hpp>
97
+ #include <cluaupp/libs/janitor.hpp>
98
+ #include <cluaupp/libs/net.hpp>
99
+ #include "../../../shared/constants/ShopCatalog.hpp"
100
+
101
+ Janitor* janitor = new Janitor();
102
+ NetEvent* Buy = Net::Event("Buy");
103
+
104
+ void OnHealthPackClicked() {
105
+ Buy->FireServer(PRODUCT_HEALTH_PACK);
106
+ }
107
+
108
+ void init() {
109
+ return;
110
+ }
111
+ ```
112
+
113
+ Wire `OnHealthPackClicked` to a `TextButton->MouseButton1Click.Connect(OnHealthPackClicked)` when you have the GUI. The remote payload is only the product id.
114
+
115
+ ## Rules
116
+
117
+ - `productId < 1` / unknown id → `PriceOf` returns `0` → reject.
118
+ - Do not `FireServer(price)` or `FireServer(newMoney)`.
119
+ - [Leaderstats](leaderstats.md) updates from `GetChangedSignal` after `Set`.
120
+ - Same Net name `"Buy"` on both sides.
121
+
122
+ See [Safety](../cpp-safety.md).
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: Sword (Touched)
3
+ sidebar_position: 7
4
+ ---
5
+
6
+ # Sword (Touched)
7
+
8
+ Melee that uses a **server** `Touched` on the tool handle. The client can play animations; it must not tell the server how much damage to apply.
9
+
10
+ Same authority as [combat](combat.md), without a Net remote: while the Tool is equipped, `Touched` runs on the server.
11
+
12
+ ## Config
13
+
14
+ `src/shared/constants/SwordConfig.hpp`
15
+
16
+ ```cpp
17
+ #pragma once
18
+
19
+ const double SWORD_COOLDOWN = 0.35;
20
+ const int SWORD_DAMAGE = 18;
21
+ ```
22
+
23
+ ## Script inside the Tool
24
+
25
+ Put the source next to the Tool so `script->Parent` is the `Tool`. Use **`.legacy.server.cpp`** so Cluaupp emits a 1:1 Script (no Main/Controller split) that Rojo can parent under `ClassicSword`.
26
+
27
+ `src/server/tools/Sword.legacy.server.cpp`
28
+
29
+ ```cpp
30
+ #include <cluaupp/roblox.hpp>
31
+ #include "../../shared/constants/SwordConfig.hpp"
32
+
33
+ Players* Players = GetService<Players>();
34
+ Tool* tool = script->Parent;
35
+
36
+ void OnTouched(Instance* hit) {
37
+ if (hit == nullptr) {
38
+ return;
39
+ }
40
+
41
+ Player* attacker = Players->GetPlayerFromCharacter(tool->Parent);
42
+ if (attacker == nullptr) {
43
+ return;
44
+ }
45
+
46
+ NumberValue* last = attacker->FindFirstChild("LastSwordAt");
47
+ if (last != nullptr) {
48
+ if (tick() - last->Value < SWORD_COOLDOWN) {
49
+ return;
50
+ }
51
+ }
52
+
53
+ Instance* model = hit->FindFirstAncestorOfClass("Model");
54
+ if (model == nullptr) {
55
+ return;
56
+ }
57
+ Player* victim = Players->GetPlayerFromCharacter(model);
58
+ if (victim == nullptr) {
59
+ return;
60
+ }
61
+ if (victim == attacker) {
62
+ return;
63
+ }
64
+
65
+ Humanoid* humanoid = model->FindFirstChildOfClass("Humanoid");
66
+ if (humanoid == nullptr) {
67
+ return;
68
+ }
69
+ if (humanoid->Health <= 0) {
70
+ return;
71
+ }
72
+
73
+ if (last == nullptr) {
74
+ last = new NumberValue(attacker);
75
+ last->Name = "LastSwordAt";
76
+ }
77
+ last->Value = tick();
78
+ humanoid->TakeDamage(SWORD_DAMAGE);
79
+ }
80
+
81
+ void init() {
82
+ BasePart* handle = tool->FindFirstChild("Handle");
83
+ if (handle == nullptr) {
84
+ cout::warn << "ClassicSword missing Handle" << endl;
85
+ return;
86
+ }
87
+ handle->Touched.Connect(OnTouched);
88
+ }
89
+ ```
90
+
91
+ `tool->Parent` is the Character while equipped, `nil` in the backpack — `GetPlayerFromCharacter` then fails and the swing is ignored. That is what you want.
92
+
93
+ ## Why `.legacy`
94
+
95
+ A tagged `Sword.server.cpp` in `src/server/` becomes a service folder in ServerScriptService. A Tool Script must live **under the Tool**. Legacy keeps one file you can Rojo-map into `ClassicSword`.
96
+
97
+ ## Rules
98
+
99
+ | Do | Do not |
100
+ | --- | --- |
101
+ | `TakeDamage(SWORD_DAMAGE)` on the server | `FireServer(damage)` from a LocalScript |
102
+ | Skip `victim == attacker` | Damage the owner when the handle clips their own parts |
103
+ | Cooldown on the attacker | Trust `Touched` rate (it fires every physics step) |
104
+ | `GetPlayerFromCharacter` | Treat every Humanoid as a player if you only want PvP |
105
+
106
+ Client: a LocalScript in the same Tool can play an AnimationTrack on `Activated`. It still must not replicate a damage number.
107
+
108
+ For ranged hits (mouse target → remote), use [combat](combat.md).
@@ -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
 
@@ -122,13 +123,15 @@ If a file defines `void init()`, Cluaupp calls `init()` at the end of the `.luau
122
123
 
123
124
  ## IntelliSense
124
125
 
125
- `cluaupp init` copies `include/cluaupp/roblox.hpp`, `.vscode/c_cpp_properties.json`, and `compile_flags.txt` (clangd). `cluaupp build` refreshes `include/cluaupp/` so completions stay in sync with the compiler.
126
+ `cluaupp init` writes the C++ IntelliSense config and installs Microsoft `ms-vscode.cpptools` (via VSIX on Cursor). Then reload the window.
126
127
 
127
- In this repo the include path is `cluau/include` (and `game/include`). After opening a `.cpp` file, complete `Player`, `FindFirstChild`, `GetPlayers`, and `Vector3`.
128
+ ```bash
129
+ cluaupp intellisense
130
+ ```
128
131
 
129
- The header is **not** compiled to Luau; it only feeds the C++ language server. Use `#include <cluaupp/roblox.hpp>` at the top of each source file.
132
+ `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is **not** compiled to Luau.
130
133
 
131
- Reload the window (Command Palette → **Developer: Reload Window**) if completions were missing before the include path existed.
134
+ See [IntelliSense](intellisense.md).
132
135
 
133
136
  ## Watch
134
137
 
@@ -153,17 +156,21 @@ void init() {
153
156
  }
154
157
  ```
155
158
 
156
- Wally is optional. Fusion, Cmdr, DataServiceV2, and the rest ship **inside** `libs/` (full GitHub source). See [Libraries](libraries.md).
159
+ Wally is optional. Fusion, Cmdr, DataServiceV2, and the rest ship **inside** `libs/` (full GitHub source). See [Libraries](libraries/index.md) — start with [DataService Init](libraries/dataservice.md) and [Janitor](libraries/janitor.md).
157
160
 
158
- See [Libraries](libraries.md), [types](cpp-types.md), [safety](cpp-safety.md).
161
+ See [Libraries](libraries/index.md), [OOP](oop/index.md), [types](cpp-types.md), [safety](cpp-safety.md).
159
162
 
160
163
  ## Next
161
164
 
162
165
  - [C++ → Luau syntax](syntax.md)
166
+ - [print and cout](print-cout.md)
163
167
  - [C++ types](cpp-types.md)
164
168
  - [const](cpp-const.md)
165
169
  - [Safety](cpp-safety.md)
166
170
  - [Organization](cpp-organization.md)
167
171
  - [Architecture](architecture.md)
172
+ - [OOP structure](oop/index.md)
173
+ - [Libraries](libraries/index.md)
174
+ - [Examples](examples/index.md)
168
175
  - [Roblox API](roblox-api.md)
169
176
  - [CLI](cli.md)
@@ -0,0 +1,31 @@
1
+ # IntelliSense
2
+
3
+ `cluaupp init` and `cluaupp intellisense` install the same setup that works in Cursor:
4
+
5
+ 1. Microsoft [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) (`ms-vscode.cpptools`)
6
+ 2. `.vscode/c_cpp_properties.json` — LLVM `clang++`, C++20, `include/` + `src/`, `compile_commands.json`
7
+ 3. Forced include of `include/cluaupp/roblox.hpp` so `GetService`, `Player`, `Janitor` complete
8
+ 4. The Cluaupp completion engine (Roblox APIs + your `struct`s)
9
+
10
+ Cursor’s marketplace does not list `ms-vscode.cpptools`. Cluaupp downloads the official VSIX from [vscode-cpptools releases](https://github.com/microsoft/vscode-cpptools/releases) and runs `cursor --install-extension`.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ cluaupp intellisense
16
+ ```
17
+
18
+ Reload: Command Palette → **Developer: Reload Window**. Status bar `{} C++` should read **IntelliSense: Ready**.
19
+
20
+ `cluaupp build` / `watch` only refresh `compile_commands.json` (no download). They never keep deleted files in the compilation database.
21
+
22
+ ## Config that ships
23
+
24
+ | File | Role |
25
+ | --- | --- |
26
+ | `.vscode/c_cpp_properties.json` | compiler path, include path, `compileCommands` |
27
+ | `.vscode/settings.json` | `C_Cpp.intelliSenseEngine: default`, `clangd.enable: false` |
28
+ | `.vscode/extensions.json` | recommends `ms-vscode.cpptools` |
29
+ | `compile_commands.json` | one entry per `src/` file |
30
+
31
+ `#include <cluaupp/roblox.hpp>` at the top of each source file. The header is not compiled to Luau.
package/docs/intro.md CHANGED
@@ -5,9 +5,9 @@ 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
- This site is built with [Moonwave](https://eryn.io/moonwave/) for local markdown docs (`npm run docs`). The public site is the cinematic engine dump at [GitHub Pages](https://kartzrbx.github.io/Cluaupp/). The language is in the same spirit as [roblox-ts](https://roblox-ts.com): a familiar syntax, a restricted subset, readable output.
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
 
12
12
  ## What you get
13
13
 
@@ -34,4 +34,4 @@ void init() {
34
34
  }
35
35
  ```
36
36
 
37
- Read [Getting started](getting-started.md), then [C++ types](cpp-types.md) and [Libraries](libraries.md).
37
+ Read [Getting started](getting-started.md), then [Examples](examples/index.md), [Libraries](libraries/index.md), and [OOP structure](oop/index.md).
@@ -0,0 +1,5 @@
1
+ {
2
+ "label": "Libraries",
3
+ "position": 20,
4
+ "collapsed": false
5
+ }
@@ -0,0 +1,104 @@
1
+ ---
2
+ title: DataService
3
+ sidebar_position: 2
4
+ ---
5
+
6
+ # DataService
7
+
8
+ Player profiles (DataServiceV2). Header: `#include <cluaupp/libs/dataservice.hpp>`.
9
+
10
+ The **save shape is yours**. Do not put `Currencies` / `Money` on the library `DataPath` type. Define a struct in the game (shared header) and pass it as `.Template`.
11
+
12
+ ## 1. Template (shared)
13
+
14
+ ```cpp
15
+ #pragma once
16
+
17
+ struct TemplateData {
18
+ struct Currencies {
19
+ int Money = 0;
20
+ int Level = 1;
21
+ } Currencies;
22
+ };
23
+ ```
24
+
25
+ Luau `DataService.Paths` follows this table (`Paths.Currencies.Money`).
26
+
27
+ ## 2. Start the server
28
+
29
+ Call **once** from a server boot script (`DataBoot.server.cpp`). `void init()` is what Cluaupp runs (not `int main()`).
30
+
31
+ ```cpp
32
+ #include <cluaupp/roblox.hpp>
33
+ #include <cluaupp/libs/dataservice.hpp>
34
+ #include "../../shared/constants/TemplateData.hpp"
35
+
36
+ void init() {
37
+ TemplateData playerData = TemplateData {};
38
+ DataService::Server.Init(DataServiceOptions {
39
+ .Template = playerData,
40
+ .StoreName = "PlayerData",
41
+ .UseMock = true,
42
+ });
43
+ }
44
+ ```
45
+
46
+ | Field | Meaning |
47
+ | --- | --- |
48
+ | `.Template` | Default document. Must match the save struct. |
49
+ | `.StoreName` | DataStore name (or a version string you own). |
50
+ | `.UseMock` | `true` in Studio / tests so you do not hit the live store. |
51
+ | `.KeyPrefix` | Optional prefix on profile keys. |
52
+ | `.StrictPaths` | Reject unknown path segments. |
53
+ | `.AutoCreateMissingTables` | Create missing nested tables on write. |
54
+
55
+ ## 3. Start the client
56
+
57
+ ```cpp
58
+ #include <cluaupp/roblox.hpp>
59
+ #include <cluaupp/libs/dataservice.hpp>
60
+
61
+ void init() {
62
+ DataService::Client.Init();
63
+ }
64
+ ```
65
+
66
+ ## 4. Read / wait
67
+
68
+ ```cpp
69
+ Data* data = DataService::Server.WaitFor(player);
70
+ if (data == nullptr) {
71
+ return;
72
+ }
73
+
74
+ int money = data->Get(DataService::Server.Paths.Currencies.Money);
75
+ ```
76
+
77
+ - `WaitFor` — yield until the profile exists.
78
+ - `Get(player)` — already loaded or `nullptr`.
79
+ - `data->Get()` with no path — whole table.
80
+ - `GetPersisted` / `GetTransient` — saved vs session-only.
81
+
82
+ Client: `DataService::Client.WaitForData()` / `Get()`.
83
+
84
+ ## 5. Write and listen
85
+
86
+ ```cpp
87
+ data->Set(DataService::Server.Paths.Currencies.Money, 10);
88
+
89
+ void OnCurrenciesChanged() {
90
+ return;
91
+ }
92
+
93
+ data->GetChangedSignal(DataService::Server.Paths.Currencies).Connect(OnCurrenciesChanged);
94
+ ```
95
+
96
+ `GetChangedSignal` fires when that path (or a child) changes. Cluaupp has no lambdas — use a named function.
97
+
98
+ ## Rules
99
+
100
+ - Init on **server and client**. Writes that must persist belong on the server.
101
+ - Paths are not a C++ enum in the library. They exist because your Template was passed to `Init`.
102
+ - Keep boot (`Init`) in one file. Keep HUD / leaderstats in another and `WaitFor` there.
103
+
104
+ Full copies: [Data boot](../examples/data-boot.md), [Leaderstats](../examples/leaderstats.md), [HUD](../examples/hud.md).
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: Using libraries
3
+ sidebar_position: 1
4
+ ---
5
+
6
+ # Libraries
7
+
8
+ `#include <cluaupp/libs/...hpp>` is IntelliSense. `cluaupp build` copies the real Luau into `libs/` (`ReplicatedStorage.CluauppLibs`). You do not `require` by hand in C++.
9
+
10
+ | Guide | Use it when |
11
+ | --- | --- |
12
+ | [DataService](dataservice.md) | Player save data, `Init`, `WaitFor`, `GetChangedSignal` |
13
+ | [Janitor](janitor.md) | Connections, instances, cleanup on leave |
14
+ | [Promise](promise.md) | Delay, Then / Catch / Await |
15
+ | [Net](net.md) | RemoteEvent / RemoteFunction without making remotes |
16
+ | [More libraries](more.md) | FormatNumber, Fusion, Cmdr, Twinkle, MathUtils, … |
17
+
18
+ Sources: [runtime/SOURCES.md](https://github.com/KartzRbx/Cluaupp/blob/main/runtime/SOURCES.md). Re-vendor: `node scripts/vendor-libs.js`.
19
+
20
+ Wally is optional. Do not install a second Janitor from Wally — CluauppLibs already has howmanysmall/Janitor.
21
+
22
+ Copy-paste systems: [Examples](../examples/index.md).
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Janitor
3
+ sidebar_position: 3
4
+ ---
5
+
6
+ # Janitor
7
+
8
+ Cleans connections, instances, promises, and threads. Header: `#include <cluaupp/libs/janitor.hpp>`. Runtime is [howmanysmall/Janitor](https://github.com/howmanysmall/Janitor). Types come from `_impl` — there is no fake `Has` method.
9
+
10
+ ## Create and add
11
+
12
+ ```cpp
13
+ auto* janitor = new Janitor();
14
+
15
+ janitor->Add(Players->PlayerAdded.Connect(OnPlayer));
16
+ janitor->Add(part, "Destroy");
17
+ janitor->Add(print, true);
18
+ ```
19
+
20
+ | Call | Cleanup |
21
+ | --- | --- |
22
+ | `Add(connection)` | `Disconnect` |
23
+ | `Add(instance)` / `Add(instance, "Destroy")` | `Destroy` |
24
+ | `Add(fn, true)` | call the function |
25
+ | `Add(thread, true)` | `task.cancel` |
26
+
27
+ ## Indexed slots (per player)
28
+
29
+ The third argument is a namespace. Adding again with the same index removes the previous task first.
30
+
31
+ ```cpp
32
+ janitor->Add(sectionJanitor, "Destroy", player->Name);
33
+
34
+ if (janitor->Get(player->Name)) {
35
+ janitor->Remove(player->Name);
36
+ }
37
+ ```
38
+
39
+ `Remove` on a missing index is a no-op. There is **no** `Has` — use `Get`.
40
+
41
+ ## Lifetime
42
+
43
+ ```cpp
44
+ janitor->Cleanup();
45
+ janitor->Destroy();
46
+ janitor->LinkToInstance(player);
47
+ ```
48
+
49
+ - `Cleanup` — run every task, janitor stays usable.
50
+ - `Destroy` — cleanup and freeze the object.
51
+ - `LinkToInstance` — cleanup when that Instance is destroyed.
52
+
53
+ ## Promises
54
+
55
+ ```cpp
56
+ #include <cluaupp/libs/promise.hpp>
57
+
58
+ janitor->AddPromise(Promise::delay(1));
59
+ ```
60
+
61
+ Cleanup cancels or rejects the promise when the janitor runs.
62
+
63
+ ## Pattern
64
+
65
+ One janitor for the script. A **child** janitor per player, stored under `player->Name`, removed on `PlayerRemoving`. Copy: [Leaderstats](../examples/leaderstats.md).
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: More libraries
3
+ sidebar_position: 6
4
+ ---
5
+
6
+ # More libraries
7
+
8
+ Same rule: include the header, call the API. `cluaupp build` already put the Luau in `CluauppLibs`.
9
+
10
+ ## FormatNumber
11
+
12
+ ```cpp
13
+ #include <cluaupp/libs/formatnumber.hpp>
14
+
15
+ print(FormatNumber::Abbreviate(1500));
16
+ print(FormatNumber::Comma(1500));
17
+ ```
18
+
19
+ ## MathUtils
20
+
21
+ ```cpp
22
+ #include <cluaupp/libs/math.hpp>
23
+
24
+ double t = MathUtils::Lerp(0, 1, 0.5);
25
+ ```
26
+
27
+ ## Twinkle (UI)
28
+
29
+ ```cpp
30
+ #include <cluaupp/libs/twinkle.hpp>
31
+
32
+ Twinkle::Fade(frame, true);
33
+ ```
34
+
35
+ ## Module3D
36
+
37
+ ```cpp
38
+ #include <cluaupp/libs/module3d.hpp>
39
+
40
+ Module3D::Attach3D(viewport, model);
41
+ ```
42
+
43
+ ## VfxUtil
44
+
45
+ ```cpp
46
+ #include <cluaupp/libs/vfx.hpp>
47
+
48
+ VfxUtil::Emit(root);
49
+ VfxUtil::Play(emitter);
50
+ ```
51
+
52
+ ## StickyBillboard
53
+
54
+ ```cpp
55
+ #include <cluaupp/libs/stickybillboard.hpp>
56
+
57
+ auto* billboard = StickyBillboard::new_(adornee, gui);
58
+ billboard->SetText("Hello");
59
+ ```
60
+
61
+ ## Fusion / Iris / Cmdr / TopbarPlus / Chrono / EzVisualz / StateMachine / Spring / Display
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:
64
+
65
+ | Lib | Header | Upstream |
66
+ | --- | --- | --- |
67
+ | Fusion | `fusion.hpp` | [dphfox/Fusion](https://github.com/dphfox/Fusion) |
68
+ | Iris | `iris.hpp` | [SirMallard/Iris](https://github.com/SirMallard/Iris) |
69
+ | Cmdr | `cmdr.hpp` | [evaera/Cmdr](https://github.com/evaera/Cmdr) |
70
+ | TopbarPlus | `topbarplus.hpp` | [1ForeverHD/TopbarPlus](https://github.com/1ForeverHD/TopbarPlus) |
71
+ | Chrono | `chrono.hpp` | [Parihsz/Chrono](https://github.com/Parihsz/Chrono) |
72
+ | EzVisualz | `ezvisual.hpp` | [arxkdev/ezVisualz](https://github.com/arxkdev/ezVisualz) |
73
+ | StateMachine | `statemachine.hpp` | [Prooheckcp/RobloxStateMachine](https://github.com/Prooheckcp/RobloxStateMachine) |
74
+ | Spring | `spring.hpp` | [nightcycle/spring](https://github.com/nightcycle/spring) |
75
+ | Display | `display.hpp` | [nightcycle/display](https://github.com/nightcycle/display) |
76
+
77
+ ## Types-only
78
+
79
+ `ArrayIndexer` (`Table<Manifest, "Name">`) and `Occlude` (`Keys<Data, "field">`) are used by generated `{Service}Types.luau`. You rarely include them from game C++.
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: Net
3
+ sidebar_position: 5
4
+ ---
5
+
6
+ # Net
7
+
8
+ Buffer-packed remotes. Header: `#include <cluaupp/libs/net.hpp>`. Same name on server and client — you do not create `RemoteEvent` instances yourself.
9
+
10
+ ```cpp
11
+ #include <cluaupp/roblox.hpp>
12
+ #include <cluaupp/libs/net.hpp>
13
+ #include <cluaupp/libs/janitor.hpp>
14
+
15
+ void OnCoins(Player* player, int amount) {
16
+ return;
17
+ }
18
+
19
+ void init() {
20
+ auto* janitor = new Janitor();
21
+ auto* coins = Net::Event("Coins");
22
+ coins->On(OnCoins);
23
+ janitor->Add(coins);
24
+ }
25
+ ```
26
+
27
+ | Side | API |
28
+ | --- | --- |
29
+ | Server | `Fire(player, ...)`, `FireAll(...)` |
30
+ | Client | `FireServer(...)` |
31
+ | Both | `On(callback)` |
32
+
33
+ Functions: `Net::Function("Shop")`, then `Invoke` / `InvokeServer`.
34
+
35
+ Validate everything the client fires. See [safety](../cpp-safety.md). Full copies: [Combat](../examples/combat.md), [Shop](../examples/shop.md).
@@ -0,0 +1,27 @@
1
+ ---
2
+ title: Promise
3
+ sidebar_position: 4
4
+ ---
5
+
6
+ # Promise
7
+
8
+ [evaera/roblox-lua-promise](https://github.com/evaera/roblox-lua-promise). Header: `#include <cluaupp/libs/promise.hpp>`.
9
+
10
+ C++ names `Then` / `Catch` / `Await` / `Cancel` are aliases of `andThen` / `catch` / `await` / `cancel`.
11
+
12
+ ```cpp
13
+ #include <cluaupp/roblox.hpp>
14
+ #include <cluaupp/libs/promise.hpp>
15
+
16
+ void AfterWait() {
17
+ print("1s later");
18
+ }
19
+
20
+ void init() {
21
+ Promise::delay(1);
22
+ }
23
+ ```
24
+
25
+ Useful statics: `Promise::delay(seconds)`, `Promise::resolve(value)`, `Promise::reject("err")`.
26
+
27
+ Cluaupp cannot nest lambdas. Prefer `delay` plus a named callback you already have, or keep promise chains in Luau libraries you call from C++.
@@ -0,0 +1,5 @@
1
+ {
2
+ "label": "OOP structure",
3
+ "position": 16,
4
+ "collapsed": false
5
+ }