cluaupp 0.2.3 → 1.0.0
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 +10 -79
- package/README.md +42 -88
- package/docs/README.md +13 -21
- package/docs/architecture.md +13 -76
- package/docs/cli.md +12 -64
- package/docs/comparison.md +6 -24
- package/docs/config.md +6 -7
- package/docs/examples/combat.md +19 -227
- package/docs/examples/hud.md +13 -81
- package/docs/examples/index.md +9 -16
- package/docs/getting-started.md +20 -137
- package/docs/intellisense.md +5 -41
- package/docs/intro.md +16 -15
- package/docs/migration.md +38 -0
- package/docs/oop/file-tags.md +12 -36
- package/docs/oop/index.md +8 -14
- package/docs/syntax.md +54 -236
- package/editors/vscode/extension.js +1 -1
- package/editors/vscode/package.json +4 -4
- package/examples/README.md +5 -7
- package/examples/game/.vscode/extensions.json +0 -3
- package/examples/game/.vscode/settings.json +6 -14
- package/examples/game/src/client/hud.client.clpp +54 -0
- package/examples/game/src/client/init.client.clpp +6 -0
- package/examples/game/src/server/combat.server.clpp +85 -0
- package/examples/game/src/server/leaderstats.server.clpp +28 -0
- package/examples/game/src/shared/PlayerData.clh +20 -0
- package/examples/game/src/shared/config.clp +6 -0
- package/examples/game/src/shared/features.clp +88 -0
- package/generated/cli.js +40 -24
- package/generated/clpp/contract.js +5 -0
- package/generated/clpp/index.js +27 -0
- package/generated/clpp/paths.js +121 -0
- package/generated/clpp/postprocess.js +78 -0
- package/generated/clpp/runner.js +102 -0
- package/generated/compile.js +26 -138
- package/generated/intellisense.js +38 -157
- package/generated/libs.js +1 -1
- package/generated/lsp.js +1 -8
- package/generated/preprocess.js +8 -179
- package/generated/system-understander.js +1 -1
- package/generated/transpile.js +3 -50
- package/generated/utils/project.js +13 -28
- package/include/{cluaupp/datatypes.hpp → clpp/datatypes.clh} +1 -1
- package/include/{cluaupp/generated/instances.hpp → clpp/generated/instances.clh} +1 -1
- package/include/{cluaupp/libs/chrono.hpp → clpp/libs/chrono.clh} +9 -9
- package/include/{cluaupp/libs/cmdr.hpp → clpp/libs/cmdr.clh} +4 -4
- package/include/{cluaupp/libs/dataservice.hpp → clpp/libs/dataservice.clh} +8 -15
- package/include/{cluaupp/libs/display.hpp → clpp/libs/display.clh} +1 -2
- package/include/{cluaupp/libs/ezvisual.hpp → clpp/libs/ezvisual.clh} +1 -3
- package/include/{cluaupp/libs/formatnumber.hpp → clpp/libs/formatnumber.clh} +2 -3
- package/include/{cluaupp/libs/fusion.hpp → clpp/libs/fusion.clh} +5 -5
- package/include/{cluaupp/libs/iris.hpp → clpp/libs/iris.clh} +2 -2
- package/include/{cluaupp/libs/janitor.hpp → clpp/libs/janitor.clh} +1 -2
- package/include/{cluaupp/libs/module3d.hpp → clpp/libs/module3d.clh} +2 -4
- package/include/{cluaupp/libs/net.hpp → clpp/libs/net.clh} +2 -4
- package/include/{cluaupp/libs/promise.hpp → clpp/libs/promise.clh} +1 -4
- package/include/{cluaupp/libs/spring.hpp → clpp/libs/spring.clh} +1 -2
- package/include/{cluaupp/libs/statemachine.hpp → clpp/libs/statemachine.clh} +2 -3
- package/include/{cluaupp/libs/stickybillboard.hpp → clpp/libs/stickybillboard.clh} +1 -2
- package/include/{cluaupp/libs/topbarplus.hpp → clpp/libs/topbarplus.clh} +3 -4
- package/include/clpp/libs.clh +24 -0
- package/include/clpp/roblox.clh +31 -0
- package/package.json +7 -14
- package/src/cli.ts +39 -25
- package/src/clpp/contract.ts +39 -0
- package/src/clpp/index.ts +18 -0
- package/src/clpp/paths.ts +117 -0
- package/src/clpp/postprocess.ts +93 -0
- package/src/clpp/runner.ts +102 -0
- package/src/compile.ts +26 -149
- package/src/intellisense.ts +36 -165
- package/src/libs.ts +1 -1
- package/src/lsp.ts +1 -5
- package/src/preprocess.ts +8 -180
- package/src/system-understander.ts +1 -1
- package/src/transpile.ts +9 -52
- package/src/utils/project.ts +12 -28
- package/templates/game/.vscode/extensions.json +0 -3
- package/templates/game/.vscode/settings.json +6 -14
- package/templates/game/src/client/init.client.clpp +6 -0
- package/templates/game/src/server/leaderstats.server.clpp +29 -0
- package/templates/game/src/shared/config.clp +6 -0
- package/examples/game/.clangd +0 -25
- package/examples/game/compile_flags.txt +0 -6
- package/examples/game/src/client/hud.client.cpp +0 -12
- package/examples/game/src/client/init.client.cpp +0 -6
- package/examples/game/src/server/combat.server.cpp +0 -23
- package/examples/game/src/server/leaderstats.server.cpp +0 -29
- package/examples/game/src/shared/config.cpp +0 -5
- package/examples/game/src/shared/config.h +0 -5
- package/include/cluaupp/libs.hpp +0 -25
- package/include/cluaupp/roblox.hpp +0 -47
- package/src/architecture.ts +0 -500
- package/src/ast.ts +0 -37
- package/src/emit.ts +0 -609
- package/src/emitter/luau-codegen.ts +0 -187
- package/src/emitter/translators.ts +0 -168
- package/src/headers.ts +0 -233
- package/src/layout.ts +0 -114
- package/src/lex.ts +0 -158
- package/src/parse.ts +0 -729
- package/src/parser/collector.ts +0 -148
- package/src/parser/index.ts +0 -27
- package/src/tree-sitter-cpp.d.ts +0 -4
- package/src/understand.ts +0 -322
- package/templates/game/src/client/init.client.cpp +0 -6
- package/templates/game/src/server/leaderstats.server.cpp +0 -29
- package/templates/game/src/shared/config.cpp +0 -5
- package/templates/game/src/shared/config.h +0 -5
- /package/include/{cluaupp/generated/enums.hpp → clpp/generated/enums.clh} +0 -0
- /package/include/{cluaupp/libs/math.hpp → clpp/libs/math.clh} +0 -0
- /package/include/{cluaupp/libs/twinkle.hpp → clpp/libs/twinkle.clh} +0 -0
- /package/include/{cluaupp/libs/vfx.hpp → clpp/libs/vfx.clh} +0 -0
package/docs/intro.md
CHANGED
|
@@ -5,33 +5,34 @@ sidebar_position: 1
|
|
|
5
5
|
|
|
6
6
|
# Cluaupp
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**CL++ on Roblox.** You write [CL++](https://kartzrbx.github.io/CLPP/). Cluaupp runs `clpp`, maps libraries into `ReplicatedStorage.CluauppLibs`, and syncs with Rojo.
|
|
9
9
|
|
|
10
|
-
This site
|
|
10
|
+
This site covers the **toolchain** (`init`, `build`, `watch`, libs). The language course is on the [CL++ site](https://kartzrbx.github.io/CLPP/).
|
|
11
11
|
|
|
12
12
|
## What you get
|
|
13
13
|
|
|
14
|
-
1.
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
17
|
-
4. Wally wrappers for DataServiceV2, Fusion, Cmdr, EzVisualz, TopbarPlus, and the rest of your stack
|
|
14
|
+
1. CLI: `cluaupp init` / `build` / `watch`
|
|
15
|
+
2. First-party libraries in `ReplicatedStorage.CluauppLibs`
|
|
16
|
+
3. Rojo project mapping (`out/server`, `out/client`, `out/shared`)
|
|
18
17
|
|
|
19
18
|
## First program
|
|
20
19
|
|
|
21
|
-
```
|
|
22
|
-
#include <
|
|
23
|
-
#include <
|
|
20
|
+
```clpp
|
|
21
|
+
#include <clpp/roblox.clh>
|
|
22
|
+
#include <clpp/libs/janitor.clh>
|
|
24
23
|
|
|
25
24
|
void OnPlayer(Player* player) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
guard (player != null) else {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
Janitor* janitor = new Janitor();
|
|
29
|
+
janitor::LinkToInstance(player);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
void init() {
|
|
32
|
-
|
|
33
|
-
players
|
|
33
|
+
Players* players = GetService<Players>();
|
|
34
|
+
players::PlayerAdded~>Connect(OnPlayer);
|
|
34
35
|
}
|
|
35
36
|
```
|
|
36
37
|
|
|
37
|
-
Read [Getting started](getting-started.md),
|
|
38
|
+
Read [Getting started](getting-started.md), [syntax](syntax.md), and [migration](migration.md).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Migrate C++ games to CL++
|
|
2
|
+
|
|
3
|
+
Cluaupp 1.0 compiles **CL++**, not a C++ subset. Language docs: [kartzrbx.github.io/CLPP](https://kartzrbx.github.io/CLPP/).
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
| Before | After |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `*.server.cpp` | `*.server.clpp` |
|
|
10
|
+
| `*.client.cpp` | `*.client.clpp` |
|
|
11
|
+
| untagged `*.cpp` | `*.clp` |
|
|
12
|
+
| `*.h` / `*.hpp` | `*.clh` |
|
|
13
|
+
|
|
14
|
+
`#include <cluaupp/roblox.hpp>` → `#include <clpp/roblox.clh>`
|
|
15
|
+
`#include <cluaupp/libs/janitor.hpp>` → `#include <clpp/libs/janitor.clh>`
|
|
16
|
+
Quoted includes: `"leaderstats.h"` → `"leaderstats.clh"`.
|
|
17
|
+
|
|
18
|
+
## Operators and IO
|
|
19
|
+
|
|
20
|
+
| Old C++ subset | CL++ | Luau |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `player->Name` | `player.Name` | `.` |
|
|
23
|
+
| `player->GetPlayers()` | `player::GetPlayers()` | `:` |
|
|
24
|
+
| `DataService::Server` | `DataService:Server` | `.` |
|
|
25
|
+
| `"hi " + name` | `"hi " .: name` | `..` |
|
|
26
|
+
| `signal.Connect(fn)` | `signal~>Connect(fn)` | Janitor `Add` |
|
|
27
|
+
| `print` / `error` | `post` / `report` | `print` / `error` |
|
|
28
|
+
| `nullptr` | `null` | `nil` |
|
|
29
|
+
| `[](Player* p) { }` | `func [](Player* p) { }` | `function` |
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
1. Install CL++: [github.com/KartzRbx/CLPP](https://github.com/KartzRbx/CLPP) (`cargo install --path .`).
|
|
34
|
+
2. `clpp install` (editor highlighting + IntelliSense).
|
|
35
|
+
3. Rename sources and apply the table above.
|
|
36
|
+
4. `cluaupp build` — `clpp` must be on PATH (`CLPP_PATH` if needed).
|
|
37
|
+
|
|
38
|
+
`"architecture": true` (ForeverHD folders) is not generated in 1.0. One source file still becomes one `.luau` file.
|
package/docs/oop/file-tags.md
CHANGED
|
@@ -5,44 +5,20 @@ sidebar_position: 2
|
|
|
5
5
|
|
|
6
6
|
# File tags
|
|
7
7
|
|
|
8
|
-
The **filename** decides the Roblox instance
|
|
8
|
+
The **filename** decides the Roblox instance (same idea as roblox-ts).
|
|
9
9
|
|
|
10
|
-
| Source | Instance |
|
|
11
|
-
| --- | --- |
|
|
12
|
-
| `LeaderstatsServer.server.
|
|
13
|
-
| `
|
|
14
|
-
| `Tools.plugin.
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
17
|
-
| `Boot.legacy.client.cpp` | LocalScript | Legacy |
|
|
18
|
-
| `Damage.cpp` (no tag) | **ModuleScript** | — |
|
|
19
|
-
| `LeaderstatsServer.h` | **ModuleScript** (types) | — |
|
|
20
|
-
| `LeaderstatsServer.cpp` (sibling of `.h`) | **ModuleScript** (`*Impl`) | — |
|
|
21
|
-
|
|
22
|
-
## One file in, one file out
|
|
23
|
-
|
|
24
|
-
Rojo infers the instance from the filename key: `*.server.luau` is a Script, `*.client.luau` is a LocalScript, untagged `.luau` is a ModuleScript.
|
|
10
|
+
| Source | Instance |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `LeaderstatsServer.server.clpp` | Script |
|
|
13
|
+
| `Hud.client.clpp` | LocalScript |
|
|
14
|
+
| `Tools.plugin.clpp` | Plugin Script |
|
|
15
|
+
| `damage.clp` (no tag) | ModuleScript |
|
|
16
|
+
| `PlayerData.clh` | ModuleScript |
|
|
25
17
|
|
|
26
18
|
```
|
|
27
|
-
src/server/boot/DataBoot.server.
|
|
28
|
-
src/client/
|
|
29
|
-
src/shared/
|
|
30
|
-
src/server/services/leaderstats/LeaderstatsServer.h → LeaderstatsServer.luau (export type)
|
|
31
|
-
src/server/services/leaderstats/LeaderstatsServer.cpp → LeaderstatsServerImpl.luau
|
|
19
|
+
src/server/boot/DataBoot.server.clpp → out/server/boot/DataBoot.server.luau
|
|
20
|
+
src/client/hud.client.clpp → out/client/hud.client.luau
|
|
21
|
+
src/shared/config.clp → out/shared/config.luau
|
|
32
22
|
```
|
|
33
23
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Where files live
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
src/server/.../*.server.cpp → out/server (ServerScriptService.Cluaupp)
|
|
40
|
-
src/client/.../*.client.cpp → out/client (StarterPlayerScripts.Cluaupp)
|
|
41
|
-
src/shared/.../*.cpp → out/shared (ReplicatedStorage.Cluaupp)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Name the **system**, not `init.server.cpp`. `LeaderstatsServer.server.cpp` and `DataBoot.server.cpp` are two files.
|
|
45
|
-
|
|
46
|
-
## Opt-in planner
|
|
47
|
-
|
|
48
|
-
`"architecture": true` in `cluaupp.config.json` restores PascalCase service folders (`Main`, Controller, Types). Default is off.
|
|
24
|
+
Language details: [CL++ docs](https://kartzrbx.github.io/CLPP/).
|
package/docs/oop/index.md
CHANGED
|
@@ -5,16 +5,14 @@ sidebar_position: 1
|
|
|
5
5
|
|
|
6
6
|
# Structs and methods
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Language details: [CL++](https://kartzrbx.github.io/CLPP/). Filename tags decide Script / LocalScript / ModuleScript.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Declare the type in a `.clh`, implement `Class::Method` in a `.clp` / `.clpp`. Capture one service table in `void init()`.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
```cpp
|
|
12
|
+
```clpp
|
|
15
13
|
#pragma once
|
|
16
|
-
#include <
|
|
17
|
-
#include <
|
|
14
|
+
#include <clpp/roblox.clh>
|
|
15
|
+
#include <clpp/libs/janitor.clh>
|
|
18
16
|
|
|
19
17
|
struct LeaderstatsServer {
|
|
20
18
|
static constexpr int STARTING_COINS = 0;
|
|
@@ -24,12 +22,8 @@ struct LeaderstatsServer {
|
|
|
24
22
|
};
|
|
25
23
|
```
|
|
26
24
|
|
|
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.
|
|
28
|
-
|
|
29
25
|
| Page | What you learn |
|
|
30
26
|
| --- | --- |
|
|
31
|
-
| [File tags](file-tags.md) | `.server` / `.client` / `.
|
|
32
|
-
| [Services](services.md) |
|
|
33
|
-
| [Modules](modules.md) |
|
|
34
|
-
|
|
35
|
-
Planner: [Architecture](../architecture.md). Folder layout: [Organization](../cpp-organization.md). Full copy: [Leaderstats](../examples/leaderstats.md).
|
|
27
|
+
| [File tags](file-tags.md) | `.server.clpp` / `.client.clpp` / `.clh` |
|
|
28
|
+
| [Services](services.md) | `init()` singletons |
|
|
29
|
+
| [Modules](modules.md) | shared `.clp` |
|
package/docs/syntax.md
CHANGED
|
@@ -1,262 +1,80 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CL++ syntax (Cluaupp)
|
|
2
2
|
|
|
3
|
-
Cluaupp
|
|
3
|
+
Cluaupp does **not** define the language. Write CL++ (`.clpp` / `.clp` / `.clh`); `clpp` emits Luau. Full course and reference: **[kartzrbx.github.io/CLPP](https://kartzrbx.github.io/CLPP/)**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Files
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## Files and includes
|
|
10
|
-
|
|
11
|
-
- Extensions: `.cpp`, `.cc`, `.cxx`, `.c`, `.h`, `.hpp`, `.hh`
|
|
12
|
-
- Tags: `*.server.cpp` → Script, `*.client.cpp` → LocalScript, `*.plugin.cpp` → Plugin, `*.legacy*` → Legacy, untagged → ModuleScript
|
|
13
|
-
- Quoted `#include "Own.h"` (same stem as the `.cpp`) is **inlined**. Other quoted includes become `require` (Rojo path)
|
|
14
|
-
- `#include <cluaupp/roblox.hpp>` is IntelliSense only. `#include <cluaupp/libs/janitor.hpp>` also injects `require(CluauppLibs.Janitor)`
|
|
15
|
-
- `#pragma once` is ignored. Other macros are not expanded. `//` and `/* */` comments are stripped
|
|
16
|
-
- `using …;` is skipped. `namespace { }` is flattened. `enum` / `template` / `typedef` / `extern` declarations are skipped
|
|
17
|
-
|
|
18
|
-
## Types
|
|
19
|
-
|
|
20
|
-
| C++ | Luau |
|
|
7
|
+
| Source | Rojo |
|
|
21
8
|
| --- | --- |
|
|
22
|
-
| `
|
|
23
|
-
| `
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
26
|
-
| `
|
|
27
|
-
| `Player*` / `Folder*` | `Player` / `Folder` (Instance handle, not a heap address) |
|
|
28
|
-
| `LuaArray<T>` / `vector<T>` / `array<T>` / `span<T>` | `{T}` |
|
|
29
|
-
| `optional<T>` | `T?` |
|
|
30
|
-
| `const` / `static constexpr` | Luau `const` |
|
|
31
|
-
| `nullptr` | `nil` |
|
|
32
|
-
| `Vector3` `CFrame` `UDim2` `Color3` | same names (copied values) |
|
|
33
|
-
| `Enum::Material::Plastic` | `Enum.Material.Plastic` |
|
|
9
|
+
| `*.server.clpp` | Script |
|
|
10
|
+
| `*.client.clpp` | LocalScript |
|
|
11
|
+
| `*.plugin.clpp` | Plugin Script |
|
|
12
|
+
| `*.clp` / untagged `.clpp` | ModuleScript |
|
|
13
|
+
| `*.clh` | ModuleScript (types / structs) |
|
|
34
14
|
|
|
35
|
-
|
|
15
|
+
`void init()` is the script entry. There is no `int main()`.
|
|
36
16
|
|
|
37
|
-
|
|
17
|
+
## Accessors
|
|
38
18
|
|
|
39
|
-
|
|
19
|
+
CL++ does **not** use `->`.
|
|
40
20
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
21
|
+
| Write | Meaning | Luau |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `player.Name` | property | `.` |
|
|
24
|
+
| `player::FindFirstChild("x")` | method | `:` |
|
|
25
|
+
| `DataService:Server` | table key | `.` |
|
|
26
|
+
| `"hi " .: name` | concat | `..` |
|
|
27
|
+
| `signal~>Connect(fn)` | janitor Connect | `janitor:Add(..., "Disconnect")` |
|
|
28
|
+
| `signal~>Once(fn)` | one-shot | `Once` + janitor |
|
|
45
29
|
|
|
46
|
-
|
|
47
|
-
return coins;
|
|
48
|
-
}
|
|
49
|
-
```
|
|
30
|
+
`post` / `warn` / `report` → `print` / `warn` / `error`. `null` is `nil`.
|
|
50
31
|
|
|
51
|
-
|
|
52
|
-
const function CreateLeaderstats(player: Player)
|
|
53
|
-
return
|
|
54
|
-
end
|
|
32
|
+
## Exclusive CL++ (compiled by `clpp`)
|
|
55
33
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
- Only functions with a body are emitted from a `.cpp`. Prototypes in a `.h` become `export type` fields
|
|
62
|
-
- No overloading — one name, one emit. No default arguments
|
|
63
|
-
- If `void init()` exists, emit appends `init()` at the end of Scripts / LocalScripts. There is no `int main()`
|
|
64
|
-
- Shared ModuleScripts should not define `init()` unless you want them to run on `require`
|
|
65
|
-
|
|
66
|
-
## Scopes
|
|
67
|
-
|
|
68
|
-
- File-level decls become file `local` / `const`
|
|
69
|
-
- Function decls become `local` from that line to the end of the block. Nested `{ }` can shadow
|
|
70
|
-
- In `Class::Method`, `this` is `self`. Bare field names become `self.field`. Bare calls to other methods become `self:Method(...)`. Parameters and locals shadow fields
|
|
71
|
-
- Globals stay bare: `print`, `game`, `workspace`, library types, Instance types, datatypes
|
|
72
|
-
- Instances are not RAII. Leaving a block does not Destroy a Part — use Janitor
|
|
73
|
-
|
|
74
|
-
## Control flow
|
|
75
|
-
|
|
76
|
-
```cpp
|
|
77
|
-
if (player->FindFirstChild("leaderstats") != nullptr) {
|
|
34
|
+
```clpp
|
|
35
|
+
guard (player != null) else {
|
|
36
|
+
warn("Invalid player");
|
|
78
37
|
return;
|
|
79
|
-
} else {
|
|
80
|
-
print("ok");
|
|
81
38
|
}
|
|
82
39
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
CreateLeaderstats(player);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
switch (action) {
|
|
92
|
-
case "buy":
|
|
93
|
-
case "purchase":
|
|
94
|
-
Grant(player);
|
|
95
|
-
break;
|
|
96
|
-
case "sell":
|
|
97
|
-
if (amount <= 0) {
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
Take(player);
|
|
101
|
-
break;
|
|
102
|
-
default:
|
|
103
|
-
warn("unknown");
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
```luau
|
|
109
|
-
if player:FindFirstChild("leaderstats") ~= nil then
|
|
110
|
-
return
|
|
111
|
-
else
|
|
112
|
-
print("ok")
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
while true do
|
|
116
|
-
print("tick")
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
for _, player in players:GetPlayers() do
|
|
120
|
-
CreateLeaderstats(player)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
repeat
|
|
124
|
-
if action == "buy" or action == "purchase" then
|
|
125
|
-
Grant(player)
|
|
126
|
-
elseif action == "sell" then
|
|
127
|
-
if amount <= 0 then
|
|
128
|
-
break
|
|
129
|
-
end
|
|
130
|
-
Take(player)
|
|
131
|
-
else
|
|
132
|
-
warn("unknown")
|
|
133
|
-
end
|
|
134
|
-
until true
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
`switch` evaluates the discriminant **once**, then becomes `if` / `elseif` / `else` inside `repeat … until true` so `break` still exits the switch (even from inside an `if`). Stacked `case` labels share a body. There is no C-style fall-through. C-style `for (int i = 0; i < n; i++)` is not supported. No `continue`, no `do/while`, no ternary. `else if (x)` emits a nested `if` inside `else` (not Luau `elseif`).
|
|
138
|
-
|
|
139
|
-
## Expressions and operators
|
|
140
|
-
|
|
141
|
-
| C++ | Luau |
|
|
142
|
-
| --- | --- |
|
|
143
|
-
| `nullptr` | `nil` |
|
|
144
|
-
| `true` / `false` | `true` / `false` |
|
|
145
|
-
| `!=` | `~=` |
|
|
146
|
-
| `&&` | `and` |
|
|
147
|
-
| `\|\|` | `or` |
|
|
148
|
-
| `!` | `not` |
|
|
149
|
-
| `==` `+` `-` `*` `/` `<` `>` `<=` `>=` | same (`*` is multiply) |
|
|
150
|
-
| `"text"` | `"text"` |
|
|
151
|
-
| `=` | assignment |
|
|
152
|
-
| `obj->Prop` | `obj.Prop` |
|
|
153
|
-
| `obj->Method(a)` | `obj:Method(a)` if the method is a Roblox / library API |
|
|
154
|
-
| `fn(a)` | `fn(a)` |
|
|
155
|
-
| `signal.Connect(fn)` | `signal:Connect(fn)` |
|
|
156
|
-
| `Type { .Field = value }` | `{ Field = value }` |
|
|
157
|
-
| unary `-` | `-` |
|
|
40
|
+
match (child) {
|
|
41
|
+
BasePart* p => BindPart(p),
|
|
42
|
+
Model* m => post("model spawned " .: m.Name),
|
|
43
|
+
_ => warn("ignored instance")
|
|
44
|
+
};
|
|
158
45
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
```cpp
|
|
164
|
-
DataService::Server.Init(DataServiceOptions {
|
|
165
|
-
.Template = playerData,
|
|
166
|
-
.StoreName = "PlayerData",
|
|
167
|
-
.UseMock = true,
|
|
46
|
+
observable int wallet = 100;
|
|
47
|
+
wallet.OnChange(func [](int newValue) {
|
|
48
|
+
post("Coins changed to: " .: newValue);
|
|
168
49
|
});
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
```luau
|
|
172
|
-
DataService.Server:Init({
|
|
173
|
-
Template = playerData,
|
|
174
|
-
StoreName = "PlayerData",
|
|
175
|
-
UseMock = true,
|
|
176
|
-
})
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Strings and string_concat
|
|
180
|
-
|
|
181
|
-
Luau concatenates with `..`. Do not write `..` in a `.cpp`.
|
|
182
|
-
|
|
183
|
-
- If either side of `+` is a string literal, another concat, or `.Name` / `.Text` / `.DisplayName`, `+` becomes `..`
|
|
184
|
-
- `string_concat(a, b, c)` is variadic: zero args → `""`, one arg → that value, several → `(a .. b .. c)`
|
|
185
|
-
- Declared in `datatypes.hpp` (via `roblox.hpp`)
|
|
186
|
-
|
|
187
|
-
```cpp
|
|
188
|
-
return player->Name + "_LeaderstatsJanitor";
|
|
189
|
-
return string_concat(player->Name, "_", "LeaderstatsJanitor");
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
```luau
|
|
193
|
-
return player.Name .. "_LeaderstatsJanitor"
|
|
194
|
-
return (player.Name .. "_" .. "LeaderstatsJanitor")
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
## print / cout
|
|
198
|
-
|
|
199
|
-
`print`, `warn`, and `error` work as in Luau. `cout << … << endl` is the C++ spelling — each `<<` is another argument, `endl` ends the line. `cout::warn` / `cout::error` / `cout::ping` pick the Roblox function. `cerr` is `warn`. Full table: [print and cout](print-cout.md).
|
|
200
50
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
auto* janitor = new Janitor();
|
|
207
|
-
part->Size = Vector3(8, 1, 8);
|
|
208
|
-
part->CFrame = CFrame::lookAt(from, look);
|
|
209
|
-
part->Material = Enum::Material::Plastic;
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
```luau
|
|
213
|
-
local coins: IntValue = Instance.new("IntValue")
|
|
214
|
-
coins.Parent = leaderstats
|
|
215
|
-
local players: Players = game:GetService("Players")
|
|
216
|
-
local janitor = Janitor.new()
|
|
217
|
-
part.Size = Vector3.new(8, 1, 8)
|
|
218
|
-
part.CFrame = CFrame.lookAt(from, look)
|
|
219
|
-
part.Material = Enum.Material.Plastic
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
The first argument of `new Class(parent)` becomes `.Parent` for Instance classes. Libraries use `Janitor.new()`. Datatypes use `Vector3(...)`, not `new`.
|
|
223
|
-
|
|
224
|
-
## Casts
|
|
51
|
+
signal<Player*, int> OnHit;
|
|
52
|
+
OnHit~>Connect(func [](Player* player, int amount) {
|
|
53
|
+
post(player.Name .: " dmg " .: amount);
|
|
54
|
+
});
|
|
55
|
+
OnHit::Fire(player, 10);
|
|
225
56
|
|
|
226
|
-
|
|
57
|
+
array<string> names = {"Kartz", "Player1"};
|
|
58
|
+
dictionary<string, int> stats = { {"Coins", 100}, {"Gems", 50} };
|
|
227
59
|
|
|
228
|
-
|
|
60
|
+
spawn { task::wait(1); post("ready"); };
|
|
61
|
+
parallel { post("desync"); };
|
|
229
62
|
|
|
230
|
-
|
|
63
|
+
async Data* FetchData(Player* player) {
|
|
64
|
+
return await DataService:Server::WaitFor(player);
|
|
65
|
+
}
|
|
231
66
|
|
|
232
|
-
|
|
67
|
+
[[server]]
|
|
68
|
+
void SaveData(Player* player) { post(player.Name); }
|
|
233
69
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
leaderstatsServer.PlayerEntered(playerEntered);
|
|
237
|
-
});
|
|
238
|
-
game->BindToClose([&]() {
|
|
239
|
-
leaderstatsServer.janitor->Cleanup();
|
|
240
|
-
});
|
|
70
|
+
[[client]]
|
|
71
|
+
void UpdateUI() { post("ui"); }
|
|
241
72
|
```
|
|
242
73
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
How you write a type: a `struct` (or `class`) in the sibling `.h`, `Class::Method` in the `.cpp`, `void init()` to boot.
|
|
246
|
-
|
|
247
|
-
- `static constexpr` fields are `const`
|
|
248
|
-
- Fields are `self.field`. `public:` / `private:` are ignored
|
|
249
|
-
- Nested structs with defaults become nested tables (DataService Templates). `LuaArray<T>` fields stay on the table
|
|
250
|
-
- `Class::` methods emit `function Class:Method(...)`
|
|
251
|
-
- Construct **one** service table in `init()` (`LeaderstatsServer leaderstatsServer;`) and capture it in lambdas. That is the game singleton
|
|
252
|
-
- Library singletons already exist: `DataService::Server` / `Client` — `Init` once from a boot script
|
|
253
|
-
- Header-only field structs emit `const function Name()` returning defaults
|
|
254
|
-
- Untagged files of only `Class::` methods `return` the table (ModuleScript)
|
|
255
|
-
|
|
256
|
-
Stem must match: `LeaderstatsServer.h` next to `LeaderstatsServer.server.cpp`. A differently named include is a `require`, not the class body.
|
|
257
|
-
|
|
258
|
-
## Not supported
|
|
74
|
+
Fusion HUD uses `Fusion:scoped`, `Fusion:Value`, `Fusion:Computed`, `Fusion:New`. See [`examples/game`](../examples/game) (`combat.server.clpp`, `hud.client.clpp`, `features.clp`, `PlayerData.clh`).
|
|
259
75
|
|
|
260
|
-
|
|
76
|
+
## What Cluaupp adds after `clpp`
|
|
261
77
|
|
|
262
|
-
|
|
78
|
+
- `require(ClppLibs.X)` → `require(ReplicatedStorage.CluauppLibs.X)`
|
|
79
|
+
- `--!strict` from `cluaupp.config.json` / `#pragma strict`
|
|
80
|
+
- `out/` layout for Rojo (`init`, `build`, `watch`)
|
|
@@ -55,7 +55,7 @@ function activate(context) {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
const refreshDiagnostics = (document) => {
|
|
58
|
-
if (!document || document.languageId !== "cpp") {
|
|
58
|
+
if (!document || (document.languageId !== "clpp" && document.languageId !== "cpp")) {
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
if (typeof loaded.engine.diagnosticsFor !== "function") {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cluaupp-diagnostics",
|
|
3
3
|
"displayName": "Cluaupp",
|
|
4
|
-
"description": "Cluaupp
|
|
5
|
-
"version": "0.
|
|
4
|
+
"description": "Cluaupp project diagnostics. Language highlighting and IntelliSense come from clpp install (CL++).",
|
|
5
|
+
"version": "1.0.0",
|
|
6
6
|
"publisher": "kartzdev",
|
|
7
7
|
"engines": {
|
|
8
8
|
"vscode": "^1.74.0"
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"Linters"
|
|
12
12
|
],
|
|
13
13
|
"activationEvents": [
|
|
14
|
-
"onLanguage:
|
|
14
|
+
"onLanguage:clpp"
|
|
15
15
|
],
|
|
16
16
|
"main": "./extension.js",
|
|
17
17
|
"contributes": {
|
|
18
18
|
"commands": [
|
|
19
19
|
{
|
|
20
20
|
"command": "cluaupp.restartIntelliSense",
|
|
21
|
-
"title": "Cluaupp: Reload
|
|
21
|
+
"title": "Cluaupp: Reload CL++ diagnostics"
|
|
22
22
|
}
|
|
23
23
|
]
|
|
24
24
|
}
|
package/examples/README.md
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
# Sample game
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
CL++ sources for a Cluaupp project — **not** the compiler. Language samples: [CL++ examples](https://github.com/KartzRbx/CLPP/tree/main/examples).
|
|
4
4
|
|
|
5
5
|
| Folder | Rojo | Tag |
|
|
6
6
|
| --- | --- | --- |
|
|
7
|
-
| `src/server/*.server.
|
|
8
|
-
| `src/client/*.client.
|
|
9
|
-
| `src/shared
|
|
10
|
-
|
|
11
|
-
`src/` of **this repo** is the TypeScript CLI ([roblox-ts](https://github.com/roblox-ts/roblox-ts) does the same). The sample scripts live here so they never mix with `understand.ts`.
|
|
7
|
+
| `src/server/*.server.clpp` | Script | server |
|
|
8
|
+
| `src/client/*.client.clpp` | LocalScript | client |
|
|
9
|
+
| `src/shared/*.clp` / `*.clh` | ModuleScript | none |
|
|
12
10
|
|
|
13
11
|
```bash
|
|
14
12
|
cd examples/game
|
|
15
13
|
npx cluaupp build .
|
|
16
14
|
```
|
|
17
15
|
|
|
18
|
-
`cluaupp init` copies `templates/game
|
|
16
|
+
`cluaupp init` copies `templates/game`. This folder adds combat (`guard` / `match` / `signal` / `observable` / `spawn`), a Fusion HUD, `features.clp`, and `PlayerData.clh`.
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"clangd.enable": true,
|
|
3
|
-
"clangd.arguments": [
|
|
4
|
-
"--compile-commands-dir=${workspaceFolder}",
|
|
5
|
-
"--header-insertion=never",
|
|
6
|
-
"--query-driver=**/clang++*,**/clang++.exe,**/g++*,**/g++.exe"
|
|
7
|
-
],
|
|
8
2
|
"files.associations": {
|
|
9
|
-
"*.
|
|
10
|
-
"*.
|
|
11
|
-
"*.
|
|
12
|
-
"*.
|
|
13
|
-
"*.
|
|
14
|
-
"*.
|
|
15
|
-
"*.legacy.server.cpp": "cpp",
|
|
16
|
-
"*.legacy.client.cpp": "cpp"
|
|
3
|
+
"*.clpp": "clpp",
|
|
4
|
+
"*.clp": "clpp",
|
|
5
|
+
"*.clh": "clpp",
|
|
6
|
+
"*.server.clpp": "clpp",
|
|
7
|
+
"*.client.clpp": "clpp",
|
|
8
|
+
"*.plugin.clpp": "clpp"
|
|
17
9
|
}
|
|
18
10
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#pragma strict
|
|
2
|
+
#include <clpp/roblox.clh>
|
|
3
|
+
#include <clpp/libs/fusion.clh>
|
|
4
|
+
|
|
5
|
+
[[client]]
|
|
6
|
+
void init() {
|
|
7
|
+
Players* players = GetService<Players>();
|
|
8
|
+
Player* localPlayer = players.LocalPlayer;
|
|
9
|
+
guard (localPlayer != null) else {
|
|
10
|
+
report("LocalPlayer missing");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Instance* playerGui = localPlayer::WaitForChild("PlayerGui");
|
|
15
|
+
auto scope = Fusion:scoped();
|
|
16
|
+
auto Children = Fusion:Children;
|
|
17
|
+
|
|
18
|
+
auto coins = Fusion:Value(scope, 0);
|
|
19
|
+
auto title = Fusion:Computed(scope, func []() {
|
|
20
|
+
return "Coins: " .: coins();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
auto newScreenGui = Fusion:New(scope, "ScreenGui");
|
|
24
|
+
auto newFrame = Fusion:New(scope, "Frame");
|
|
25
|
+
auto newLabel = Fusion:New(scope, "TextLabel");
|
|
26
|
+
|
|
27
|
+
auto label = newLabel({
|
|
28
|
+
{"Name", "Amount"},
|
|
29
|
+
{"BackgroundTransparency", 1},
|
|
30
|
+
{"Size", UDim2.fromScale(1, 1)},
|
|
31
|
+
{"Text", title},
|
|
32
|
+
{"TextColor3", Color3.fromRGB(255, 255, 255)},
|
|
33
|
+
{"TextScaled", true}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
auto frame = newFrame({
|
|
37
|
+
{"Name", "Hud"},
|
|
38
|
+
{"AnchorPoint", Vector2(0, 1)},
|
|
39
|
+
{"Position", UDim2.fromScale(0, 1)},
|
|
40
|
+
{"Size", UDim2.fromOffset(220, 64)},
|
|
41
|
+
{"BackgroundColor3", Color3.fromRGB(28, 18, 48)},
|
|
42
|
+
{Children, label}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
newScreenGui({
|
|
46
|
+
{"Name", "CoinsHud"},
|
|
47
|
+
{"ResetOnSpawn", false},
|
|
48
|
+
{"Parent", playerGui},
|
|
49
|
+
{Children, frame}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
coins(100);
|
|
53
|
+
post("hud ready");
|
|
54
|
+
}
|