cluaupp 0.2.1 → 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 +12 -0
- package/README.md +1 -1
- package/docs/README.md +32 -20
- package/docs/cli.md +1 -1
- package/docs/cpp-advanced.md +6 -3
- package/docs/cpp-types.md +2 -0
- package/docs/examples/hud.md +1 -1
- package/docs/examples/index.md +1 -1
- package/docs/examples/leaderstats.md +44 -115
- package/docs/getting-started.md +4 -2
- package/docs/intellisense.md +4 -5
- package/docs/libraries/dataservice.md +4 -1
- package/docs/libraries/index.md +2 -1
- package/docs/libraries/more.md +3 -1
- package/docs/libraries/ui.md +76 -0
- package/docs/oop/index.md +20 -7
- package/docs/roblox-api.md +4 -56
- package/docs/syntax.md +112 -55
- package/editors/vscode/package.json +25 -25
- package/examples/game/.vscode/extensions.json +3 -0
- package/examples/game/.vscode/settings.json +0 -9
- package/examples/game/src/shared/config.h +2 -0
- package/generated/api.js +15 -1
- package/generated/compile.js +38 -0
- package/generated/emit.js +79 -3
- package/generated/intellisense.js +75 -80
- package/generated/lex.js +3 -0
- package/generated/parse.js +119 -24
- package/generated/parser/collector.js +37 -1
- package/generated/utils/rojo-mapper.js +23 -3
- package/include/cluaupp/datatypes.hpp +4 -0
- package/package.json +98 -87
- package/src/api.ts +15 -1
- package/src/compile.ts +43 -1
- package/src/emit.ts +81 -3
- package/src/intellisense.ts +80 -80
- package/src/lex.ts +3 -0
- package/src/parse.ts +124 -25
- package/src/parser/collector.ts +35 -2
- package/src/utils/rojo-mapper.ts +26 -3
- package/templates/game/.vscode/extensions.json +3 -0
- package/templates/game/.vscode/settings.json +0 -9
- package/templates/game/src/shared/config.h +2 -0
- package/examples/game/.vscode/c_cpp_properties.json +0 -27
- package/templates/game/.vscode/c_cpp_properties.json +0 -27
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
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
|
+
|
|
13
|
+
## 0.2.2
|
|
14
|
+
|
|
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`).
|
|
16
|
+
|
|
5
17
|
## 0.2.1
|
|
6
18
|
|
|
7
19
|
- Pin `tree-sitter` 0.21.1 and `tree-sitter-c` 0.23.2 so `npm i -g cluaupp` no longer pulls `tree-sitter-c@0.23.6` (peerOptional `tree-sitter@^0.22.1`).
|
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/) · [
|
|
9
|
+
[Docs](https://kartzrbx.github.io/Cluaupp/) · [Handbook](https://kartzrbx.github.io/Cluaupp/docs/)
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/cluaupp)
|
|
12
12
|
[](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,
|
|
5
|
-
3. [CLI](cli.md) — `init`, `build`, `watch`
|
|
6
|
-
4. [
|
|
7
|
-
5. [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
package/docs/cpp-advanced.md
CHANGED
|
@@ -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
|
|
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
|
package/docs/examples/hud.md
CHANGED
|
@@ -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()`
|
|
12
|
+
Define callbacks **above** `init()` or use lambdas in `Connect`.
|
|
13
13
|
|
|
14
14
|
## `HudClient.client.cpp`
|
|
15
15
|
|
package/docs/examples/index.md
CHANGED
|
@@ -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()`.
|
|
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
|
-
|
|
8
|
+
Canonical copy (three files): [Docs → Example: Leaderstats](https://kartzrbx.github.io/Cluaupp/docs/leaderstats.html).
|
|
9
9
|
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
|
17
|
-
|
|
|
18
|
-
| `
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
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
|
-
##
|
|
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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
103
|
-
if (janitor->Get(player->Name)) {
|
|
104
|
-
janitor->Remove(player->Name);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
51
|
+
## `PlayerEntered`
|
|
107
52
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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(
|
|
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
|
-
|
|
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).
|
package/docs/getting-started.md
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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)
|
package/docs/intellisense.md
CHANGED
|
@@ -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/`
|
|
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
|
|
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/
|
|
43
|
-
| `.vscode/
|
|
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.
|
|
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
|
|
package/docs/libraries/index.md
CHANGED
|
@@ -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
|
-
| [
|
|
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
|
|
package/docs/libraries/more.md
CHANGED
|
@@ -60,7 +60,9 @@ billboard->SetText("Hello");
|
|
|
60
60
|
|
|
61
61
|
## Fusion / Iris / Cmdr / TopbarPlus / Chrono / EzVisualz / StateMachine / Spring / Display
|
|
62
62
|
|
|
63
|
-
|
|
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
|
-
#
|
|
6
|
+
# Structs and methods
|
|
7
7
|
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
35
|
+
Planner: [Architecture](../architecture.md). Folder layout: [Organization](../cpp-organization.md). Full copy: [Leaderstats](../examples/leaderstats.md).
|
package/docs/roblox-api.md
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
# Roblox API
|
|
2
2
|
|
|
3
|
-
Cluaupp
|
|
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
|
-
|
|
5
|
+
Handbook: **[Docs](https://kartzrbx.github.io/Cluaupp/docs/)** · [Roblox in Cluaupp](https://kartzrbx.github.io/Cluaupp/docs/engine.html)
|
|
6
6
|
|
|
7
|
-
|
|
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
|
-
|
|
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")`.
|