Skip to content

Advanced

CL++ is the language (clpp 0.3.2). Cluaupp orchestrates Rojo and CluauppLibs. Full course: kartzrbx.github.io/CLPP.

  • .clpp / .clp / .clh, tags .server / .client, #pragma strict, void init()
  • if / else / while / C-style for / range-for (T x in list) / switch / guard / match
  • struct + Class::Method, new Class(parent), GetService<T>(), static_cast<T>(x)
  • Property ., instance method ., static ::, Janitor Connect ~>, concat .:
  • Lambdas func (params) { }
  • post / warn / report, null, observable, signal, spawn / parallel
  • Quoted includes; angled #include <clpp/...> is IntelliSense-only
  • Libraries via #include <clpp/libs/sweep.clh>require(ReplicatedStorage.CluauppLibs.Sweep)

->, continue, ternary, do/while, try/catch, goto, (void)x, func [](…), []() { }, C++ captures [&], Player*, ISO std::, JSX.

If you need a custom type, it is usually a ModuleScript in shared (a .clp) or a Wally package.

CL++LuauWhen
player.Nameplayer.Nameproperty
player.FindFirstChild("x")player:FindFirstChild("x")instance method
CFrame::lookAt(a, b)CFrame.lookAt(a, b)static / datatype
DataService.ServerDataService.Servertable key (. only — not :)
players.PlayerAdded~>Connect(fn)janitor:Add(..., "Disconnect")default listen
signal::Connect(fn)signal:Connect(fn)you Disconnect
for (Player p in list)for _, p in list dorange-for

If a file defines void init(), clpp calls init() at the end of Scripts / LocalScripts. Shared modules (.clp) should not define init() unless you want them to run on require.

CluauppLibs already contains Janitor, Fusion, Cmdr, DataServiceV2, … (copied into runtime/). Add Wally only for packages that are not in CluauppLibs. Headers live in include/clpp/libs/.

#include <clpp/libs/keep.clh>
void Grant(Player player, int amount) {
Data data = DataService.Server.WaitFor(player);
guard (data != null) else {
return;
}
int coins = data.Get(DataService.Server.Paths.Currencies.Coins);
data.Set(DataService.Server.Paths.Currencies.Coins, coins + amount);
}

Paths.Currencies.Coins exists because your Template passed to Init had that field.

  • Prefer const and locals over recomputing in RenderStepped.
  • Net already uses buffer. Batch when you can; do not fire per-heartbeat for every NPC.
  • Janitor Cleanup is O(tracked objects). Link to the Instance that owns the scope.
  1. Initialize everything. int coins; without a value is a bug; write int coins = 0.
  2. Small functions. One behavior, named after the behavior.
  3. No magic numbers. const int MAX_INVENTORY = 20.
  4. Early return. Flatten if pyramids.
  5. Headers declare, scripts define. Prototypes in .clh, bodies in .clp / .clpp.
  6. Do not share mutable statics across server and client — use Net or DataService.

See also: syntax, libraries. Language: kartzrbx.github.io/CLPP.