cluaupp 1.5.1 → 1.5.2

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 (64) hide show
  1. package/examples/game/cluaupp.config.json +1 -1
  2. package/examples/game/default.project.json +13 -16
  3. package/examples/game/src/Client/Main.client.clpp +4 -0
  4. package/examples/game/src/{ServerScriptService → Server}/Boot/DataBoot.server.clpp +1 -1
  5. package/examples/game/src/Server/Main.server.clpp +4 -0
  6. package/generated/clpp/modules.js +5 -0
  7. package/generated/target/gen-rojo-tree.js +118 -0
  8. package/generated/utils/project.js +8 -0
  9. package/package.json +2 -2
  10. package/src/clpp/modules.ts +5 -0
  11. package/src/target/gen-rojo-tree.ts +123 -0
  12. package/src/utils/project.ts +9 -0
  13. package/templates/game/cluaupp.config.json +1 -1
  14. package/templates/game/default.project.json +13 -16
  15. package/templates/game/src/Client/Main.client.clpp +4 -0
  16. package/templates/game/src/{ServerScriptService → Server}/Boot/DataBoot.server.clpp +1 -1
  17. package/templates/game/src/Server/Main.server.clpp +4 -0
  18. package/examples/game/src/ReplicatedFirst/Loading/.gitkeep +0 -1
  19. package/examples/game/src/ReplicatedStorage/Shared/Constants/Classes/.gitkeep +0 -1
  20. package/examples/game/src/ReplicatedStorage/Shared/Constants/Primitives/.gitkeep +0 -1
  21. package/examples/game/src/ReplicatedStorage/Shared/Modules/.gitkeep +0 -1
  22. package/examples/game/src/ReplicatedStorage/Shared/Net/.gitkeep +0 -1
  23. package/examples/game/src/ReplicatedStorage/Shared/Net/Net.clh +0 -26
  24. package/examples/game/src/ReplicatedStorage/Shared/Services/.gitkeep +0 -1
  25. package/examples/game/src/ReplicatedStorage/Shared/Types/.gitkeep +0 -1
  26. package/examples/game/src/ReplicatedStorage/Shared/Utils/.gitkeep +0 -1
  27. package/examples/game/src/ServerScriptService/Components/.gitkeep +0 -1
  28. package/examples/game/src/ServerScriptService/Configuration/ServerConfig.clp +0 -4
  29. package/examples/game/src/ServerScriptService/Services/.gitkeep +0 -1
  30. package/examples/game/src/ServerStorage/Configuration/.gitkeep +0 -1
  31. package/examples/game/src/ServerStorage/Modules/.gitkeep +0 -1
  32. package/examples/game/src/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.clpp +0 -6
  33. package/examples/game/src/StarterPlayer/StarterCharacterScripts/Combat/.gitkeep +0 -1
  34. package/examples/game/src/StarterPlayer/StarterCharacterScripts/Movement/.gitkeep +0 -1
  35. package/examples/game/src/StarterPlayer/StarterPlayerScripts/Input/.gitkeep +0 -1
  36. package/examples/game/src/StarterPlayer/StarterPlayerScripts/UI/.gitkeep +0 -1
  37. package/templates/game/src/ReplicatedFirst/Loading/.gitkeep +0 -1
  38. package/templates/game/src/ReplicatedStorage/Shared/Constants/Classes/.gitkeep +0 -1
  39. package/templates/game/src/ReplicatedStorage/Shared/Constants/Primitives/.gitkeep +0 -1
  40. package/templates/game/src/ReplicatedStorage/Shared/Modules/.gitkeep +0 -1
  41. package/templates/game/src/ReplicatedStorage/Shared/Net/.gitkeep +0 -1
  42. package/templates/game/src/ReplicatedStorage/Shared/Services/.gitkeep +0 -1
  43. package/templates/game/src/ReplicatedStorage/Shared/Types/.gitkeep +0 -1
  44. package/templates/game/src/ReplicatedStorage/Shared/Utils/.gitkeep +0 -1
  45. package/templates/game/src/ServerScriptService/Components/.gitkeep +0 -1
  46. package/templates/game/src/ServerScriptService/Configuration/ServerConfig.clp +0 -4
  47. package/templates/game/src/ServerScriptService/Services/.gitkeep +0 -1
  48. package/templates/game/src/ServerStorage/Configuration/.gitkeep +0 -1
  49. package/templates/game/src/ServerStorage/Modules/.gitkeep +0 -1
  50. package/templates/game/src/StarterPlayer/StarterCharacterScripts/Character/CharacterReady.client.clpp +0 -6
  51. package/templates/game/src/StarterPlayer/StarterCharacterScripts/Combat/.gitkeep +0 -1
  52. package/templates/game/src/StarterPlayer/StarterCharacterScripts/Movement/.gitkeep +0 -1
  53. package/templates/game/src/StarterPlayer/StarterPlayerScripts/Input/.gitkeep +0 -1
  54. package/templates/game/src/StarterPlayer/StarterPlayerScripts/UI/.gitkeep +0 -1
  55. /package/examples/game/src/{StarterPlayer/StarterPlayerScripts → Client}/Controllers/DataController.client.clpp +0 -0
  56. /package/examples/game/src/{ReplicatedStorage/Shared/Net → Declarations}/Net.flare +0 -0
  57. /package/examples/game/src/{ReplicatedStorage/Shared/Constants/Datas/TemplateData.clh → Include/GameTypes.clh} +0 -0
  58. /package/examples/game/src/{ServerScriptService/Handlers → Modules/Core}/Guard.server.clpp +0 -0
  59. /package/examples/game/src/{ServerScriptService/Handlers → Modules/Core}/PlayerHandler.server.clpp +0 -0
  60. /package/templates/game/src/{StarterPlayer/StarterPlayerScripts → Client}/Controllers/DataController.client.clpp +0 -0
  61. /package/templates/game/src/{ReplicatedStorage/Shared/Net → Declarations}/Net.flare +0 -0
  62. /package/templates/game/src/{ReplicatedStorage/Shared/Constants/Datas/TemplateData.clh → Include/GameTypes.clh} +0 -0
  63. /package/templates/game/src/{ServerScriptService/Handlers → Modules/Core}/Guard.server.clpp +0 -0
  64. /package/templates/game/src/{ServerScriptService/Handlers → Modules/Core}/PlayerHandler.server.clpp +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "rootDir": "src",
2
+ "rootDir": "Src",
3
3
  "outDir": "out",
4
4
  "strict": false,
5
5
  "architecture": false
@@ -2,18 +2,23 @@
2
2
  "name": "cluaupp-game",
3
3
  "tree": {
4
4
  "$className": "DataModel",
5
- "ReplicatedFirst": {
6
- "$className": "ReplicatedFirst",
7
- "$path": "out/ReplicatedFirst"
8
- },
9
5
  "ServerScriptService": {
10
6
  "$className": "ServerScriptService",
11
- "$path": "out/ServerScriptService"
7
+ "$path": "out/Server",
8
+ "Parallel": {
9
+ "$path": "out/Parallel"
10
+ }
12
11
  },
13
12
  "ReplicatedStorage": {
14
13
  "$className": "ReplicatedStorage",
15
- "Shared": {
16
- "$path": "out/ReplicatedStorage/Shared"
14
+ "Declarations": {
15
+ "$path": "out/Declarations"
16
+ },
17
+ "Include": {
18
+ "$path": "out/Include"
19
+ },
20
+ "Modules": {
21
+ "$path": "out/Modules"
17
22
  },
18
23
  "CluauppLibs": {
19
24
  "$path": "libs"
@@ -23,17 +28,9 @@
23
28
  "$className": "StarterPlayer",
24
29
  "StarterPlayerScripts": {
25
30
  "$className": "StarterPlayerScripts",
26
- "$path": "out/StarterPlayer/StarterPlayerScripts"
27
- },
28
- "StarterCharacterScripts": {
29
- "$className": "StarterCharacterScripts",
30
- "$path": "out/StarterPlayer/StarterCharacterScripts"
31
+ "$path": "out/Client"
31
32
  }
32
33
  },
33
- "ServerStorage": {
34
- "$className": "ServerStorage",
35
- "$path": "out/ServerStorage"
36
- },
37
34
  "HttpService": {
38
35
  "$className": "HttpService",
39
36
  "$properties": {
@@ -0,0 +1,4 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+
4
+ void init() {}
@@ -1,7 +1,7 @@
1
1
  #pragma strict
2
2
  #include <clpp/roblox.clh>
3
3
  #include <clpp/libs/keep.clh>
4
- import { PlayerTemplate } from "../../ReplicatedStorage/Shared/Constants/Datas/TemplateData.clh";
4
+ import { PlayerTemplate } from "../../Include/GameTypes.clh";
5
5
 
6
6
  void init() {
7
7
  PlayerTemplate playerData = PlayerTemplate();
@@ -0,0 +1,4 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+
4
+ void init() {}
@@ -166,6 +166,11 @@ function rewriteGameRootedRequires(luau) {
166
166
  const re = new RegExp(`script(?:\\.Parent)+\\.${svc}\\.`, "g");
167
167
  next = next.replace(re, `${svc}.`);
168
168
  }
169
+ // Domain root folders are mapped under ReplicatedStorage by GenRojoTree.
170
+ for (const folder of ["Include", "Modules", "Declarations"]) {
171
+ const re = new RegExp(`script(?:\\.Parent)+\\.${folder}\\.`, "g");
172
+ next = next.replace(re, `ReplicatedStorage.${folder}.`);
173
+ }
169
174
  return next;
170
175
  }
171
176
  /** Ensure GetService lines exist for any game-rooted require used. */
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildRojoTree = buildRojoTree;
7
+ exports.writeDefaultProject = writeDefaultProject;
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ function walkFiles(dir, files = []) {
11
+ if (!node_fs_1.default.existsSync(dir)) {
12
+ return files;
13
+ }
14
+ for (const entry of node_fs_1.default.readdirSync(dir, { withFileTypes: true })) {
15
+ const full = node_path_1.default.join(dir, entry.name);
16
+ if (entry.isDirectory()) {
17
+ walkFiles(full, files);
18
+ continue;
19
+ }
20
+ files.push(full);
21
+ }
22
+ return files;
23
+ }
24
+ function withPath(node, relPath) {
25
+ node.$path = relPath.replace(/\\/g, "/");
26
+ }
27
+ function ensureNode(root, parts) {
28
+ let current = root;
29
+ for (const part of parts) {
30
+ const next = current[part];
31
+ if (next && typeof next === "object") {
32
+ current = next;
33
+ continue;
34
+ }
35
+ const created = {};
36
+ current[part] = created;
37
+ current = created;
38
+ }
39
+ return current;
40
+ }
41
+ function fileStem(rel) {
42
+ return rel
43
+ .replace(/\.(server|client)\.luau$/i, "")
44
+ .replace(/\.(server|client)\.(clpp|clp|clh)$/i, "")
45
+ .replace(/\.(luau|lua|clpp|clp|clh|flare|hive|mint|bloom|helm|shift|axiom)$/i, "");
46
+ }
47
+ function mapModules(rootTree, rootAbs, modulesRoot) {
48
+ if (!node_fs_1.default.existsSync(modulesRoot)) {
49
+ return;
50
+ }
51
+ const files = walkFiles(modulesRoot).filter((file) => /\.(luau|lua|clpp|clp|clh)$/i.test(file));
52
+ for (const file of files) {
53
+ const rel = node_path_1.default.relative(rootAbs, file).replace(/\\/g, "/");
54
+ const moduleRel = node_path_1.default.relative(modulesRoot, file).replace(/\\/g, "/");
55
+ const stem = fileStem(moduleRel);
56
+ const parts = stem.split("/").filter(Boolean);
57
+ if (parts.length === 0) {
58
+ continue;
59
+ }
60
+ const isServer = /\.server\.(luau|lua|clpp|clp|clh)$/i.test(file);
61
+ const isClient = /\.client\.(luau|lua|clpp|clp|clh)$/i.test(file);
62
+ const rootParts = isServer
63
+ ? ["ServerScriptService", "Modules"]
64
+ : isClient
65
+ ? ["StarterPlayer", "StarterPlayerScripts", "Modules"]
66
+ : ["ReplicatedStorage", "Modules"];
67
+ const parent = ensureNode(rootTree, [...rootParts, ...parts.slice(0, -1)]);
68
+ const leaf = ensureNode(parent, [parts[parts.length - 1]]);
69
+ withPath(leaf, rel);
70
+ }
71
+ }
72
+ function baseTree() {
73
+ return {
74
+ $className: "DataModel",
75
+ ServerScriptService: {
76
+ $className: "ServerScriptService",
77
+ },
78
+ ReplicatedStorage: {
79
+ $className: "ReplicatedStorage",
80
+ CluauppLibs: { $path: "libs" },
81
+ },
82
+ StarterPlayer: {
83
+ $className: "StarterPlayer",
84
+ StarterPlayerScripts: {
85
+ $className: "StarterPlayerScripts",
86
+ },
87
+ },
88
+ HttpService: {
89
+ $className: "HttpService",
90
+ $properties: {
91
+ HttpEnabled: true,
92
+ },
93
+ },
94
+ };
95
+ }
96
+ function buildRojoTree(root, rootDir, outDir) {
97
+ const outRoot = node_path_1.default.join(root, outDir);
98
+ const srcRoot = node_path_1.default.join(root, rootDir);
99
+ const sourceRoot = node_fs_1.default.existsSync(outRoot) ? outRoot : srcRoot;
100
+ const tree = baseTree();
101
+ const relRoot = node_path_1.default.relative(root, sourceRoot).replace(/\\/g, "/");
102
+ withPath(ensureNode(tree, ["ServerScriptService"]), `${relRoot}/Server`);
103
+ withPath(ensureNode(tree, ["ServerScriptService", "Parallel"]), `${relRoot}/Parallel`);
104
+ withPath(ensureNode(tree, ["StarterPlayer", "StarterPlayerScripts"]), `${relRoot}/Client`);
105
+ withPath(ensureNode(tree, ["ReplicatedStorage", "Declarations"]), `${relRoot}/Declarations`);
106
+ withPath(ensureNode(tree, ["ReplicatedStorage", "Include"]), `${relRoot}/Include`);
107
+ mapModules(tree, root, node_path_1.default.join(sourceRoot, "Modules"));
108
+ return tree;
109
+ }
110
+ function writeDefaultProject(root, rootDir, outDir, projectJsonPath) {
111
+ const file = node_path_1.default.resolve(root, projectJsonPath || "default.project.json");
112
+ const body = {
113
+ name: "cluaupp-game",
114
+ tree: buildRojoTree(root, rootDir, outDir),
115
+ };
116
+ node_fs_1.default.writeFileSync(file, `${JSON.stringify(body, null, "\t")}\n`, "utf8");
117
+ return file;
118
+ }
@@ -30,6 +30,7 @@ const flare_version_js_1 = require("../target/flare-version.js");
30
30
  const component_contracts_js_1 = require("../target/component-contracts.js");
31
31
  const authority_check_js_1 = require("../target/authority-check.js");
32
32
  const datamodel_js_1 = require("../target/datamodel.js");
33
+ const gen_rojo_tree_js_1 = require("../target/gen-rojo-tree.js");
33
34
  const build_cache_js_1 = require("../target/build-cache.js");
34
35
  const modules_js_1 = require("../clpp/modules.js");
35
36
  function readProjectConfig(file) {
@@ -305,6 +306,9 @@ function createMapper(root, config, rojoPath) {
305
306
  mapper.loadSync();
306
307
  return mapper;
307
308
  }
309
+ function syncRojoTree(root, config, rojoPath) {
310
+ (0, gen_rojo_tree_js_1.writeDefaultProject)(root, config.rootDir, config.outDir, rojoPath || "default.project.json");
311
+ }
308
312
  function compileOptions(root, config, file, rel) {
309
313
  const srcDir = node_path_1.default.join(root, config.rootDir);
310
314
  return {
@@ -586,6 +590,7 @@ function finishBuild(root, config, compiled, options) {
586
590
  }
587
591
  }
588
592
  const written = writeJobs(root, config, compiled.jobs, format);
593
+ syncRojoTree(root, config, options.rojo);
589
594
  try {
590
595
  const soaPlans = (0, optimizer_soa_js_1.collectSoaPlansFromProject)(root, config.rootDir);
591
596
  if (soaPlans.length) {
@@ -625,6 +630,7 @@ function prepareBuild(root, options) {
625
630
  const exitOnError = options.exitOnError !== false;
626
631
  const holdOnError = options.holdOnError === true;
627
632
  const config = loadConfig(root);
633
+ syncRojoTree(root, config, options.rojo);
628
634
  if (options.strict === true) {
629
635
  config.strict = true;
630
636
  }
@@ -700,6 +706,8 @@ async function init(dest) {
700
706
  copyDir(skills, node_path_1.default.join(target, ".cursor", "skills"));
701
707
  }
702
708
  copyRuntime(target);
709
+ const initConfig = loadConfig(target);
710
+ syncRojoTree(target, initConfig);
703
711
  (0, intellisense_js_1.syncEditorSupport)(target);
704
712
  try {
705
713
  (0, intellisense_js_1.installEditorExtension)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cluaupp",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
4
4
  "description": "Cluaupp toolchain — compile CL++ to Luau with Rojo and CluauppLibs.",
5
5
  "author": "KartzDev",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  "dev:cli": "tsx src/cli.ts",
44
44
  "prepare": "tsc",
45
45
  "postinstall": "node scripts/postinstall-editor.js",
46
- "test": "node test/security.test.js && node test/understander.test.js && node test/out.test.js && node test/types.test.js && node test/modules.test.js && node test/modules-import.test.js && node test/get-service.test.js && node test/clpp.test.js && node test/flare.test.js && node test/native.test.js && node test/postprocess.test.js && node test/api.test.js && node test/api-reuse.test.js && node test/context-safety.test.js && node test/datamodel.test.js && node test/platform-analyzers.test.js && node test/platform-extras.test.js && node test/generator.test.js && node test/studio/smoke.test.js",
46
+ "test": "node test/security.test.js && node test/understander.test.js && node test/out.test.js && node test/types.test.js && node test/modules.test.js && node test/modules-import.test.js && node test/gen-rojo-tree.test.js && node test/get-service.test.js && node test/clpp.test.js && node test/flare.test.js && node test/native.test.js && node test/postprocess.test.js && node test/api.test.js && node test/api-reuse.test.js && node test/context-safety.test.js && node test/datamodel.test.js && node test/platform-analyzers.test.js && node test/platform-extras.test.js && node test/generator.test.js && node test/studio/smoke.test.js",
47
47
  "test:clpp-contract": "node test/clpp.test.js",
48
48
  "generate-api": "node scripts/generate-api.js",
49
49
  "vendor-libs": "node scripts/vendor-libs.js",
@@ -187,6 +187,11 @@ export function rewriteGameRootedRequires(luau: string): string {
187
187
  const re = new RegExp(`script(?:\\.Parent)+\\.${svc}\\.`, "g");
188
188
  next = next.replace(re, `${svc}.`);
189
189
  }
190
+ // Domain root folders are mapped under ReplicatedStorage by GenRojoTree.
191
+ for (const folder of ["Include", "Modules", "Declarations"]) {
192
+ const re = new RegExp(`script(?:\\.Parent)+\\.${folder}\\.`, "g");
193
+ next = next.replace(re, `ReplicatedStorage.${folder}.`);
194
+ }
190
195
  return next;
191
196
  }
192
197
 
@@ -0,0 +1,123 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ type RojoNode = Record<string, unknown>;
5
+
6
+ function walkFiles(dir: string, files: string[] = []): string[] {
7
+ if (!fs.existsSync(dir)) {
8
+ return files;
9
+ }
10
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
11
+ const full = path.join(dir, entry.name);
12
+ if (entry.isDirectory()) {
13
+ walkFiles(full, files);
14
+ continue;
15
+ }
16
+ files.push(full);
17
+ }
18
+ return files;
19
+ }
20
+
21
+ function withPath(node: RojoNode, relPath: string): void {
22
+ node.$path = relPath.replace(/\\/g, "/");
23
+ }
24
+
25
+ function ensureNode(root: RojoNode, parts: string[]): RojoNode {
26
+ let current = root;
27
+ for (const part of parts) {
28
+ const next = current[part] as RojoNode | undefined;
29
+ if (next && typeof next === "object") {
30
+ current = next;
31
+ continue;
32
+ }
33
+ const created: RojoNode = {};
34
+ current[part] = created;
35
+ current = created;
36
+ }
37
+ return current;
38
+ }
39
+
40
+ function fileStem(rel: string): string {
41
+ return rel
42
+ .replace(/\.(server|client)\.luau$/i, "")
43
+ .replace(/\.(server|client)\.(clpp|clp|clh)$/i, "")
44
+ .replace(/\.(luau|lua|clpp|clp|clh|flare|hive|mint|bloom|helm|shift|axiom)$/i, "");
45
+ }
46
+
47
+ function mapModules(rootTree: RojoNode, rootAbs: string, modulesRoot: string): void {
48
+ if (!fs.existsSync(modulesRoot)) {
49
+ return;
50
+ }
51
+ const files = walkFiles(modulesRoot).filter((file) => /\.(luau|lua|clpp|clp|clh)$/i.test(file));
52
+ for (const file of files) {
53
+ const rel = path.relative(rootAbs, file).replace(/\\/g, "/");
54
+ const moduleRel = path.relative(modulesRoot, file).replace(/\\/g, "/");
55
+ const stem = fileStem(moduleRel);
56
+ const parts = stem.split("/").filter(Boolean);
57
+ if (parts.length === 0) {
58
+ continue;
59
+ }
60
+ const isServer = /\.server\.(luau|lua|clpp|clp|clh)$/i.test(file);
61
+ const isClient = /\.client\.(luau|lua|clpp|clp|clh)$/i.test(file);
62
+ const rootParts = isServer
63
+ ? ["ServerScriptService", "Modules"]
64
+ : isClient
65
+ ? ["StarterPlayer", "StarterPlayerScripts", "Modules"]
66
+ : ["ReplicatedStorage", "Modules"];
67
+ const parent = ensureNode(rootTree, [...rootParts, ...parts.slice(0, -1)]);
68
+ const leaf = ensureNode(parent, [parts[parts.length - 1]]);
69
+ withPath(leaf, rel);
70
+ }
71
+ }
72
+
73
+ function baseTree(): RojoNode {
74
+ return {
75
+ $className: "DataModel",
76
+ ServerScriptService: {
77
+ $className: "ServerScriptService",
78
+ },
79
+ ReplicatedStorage: {
80
+ $className: "ReplicatedStorage",
81
+ CluauppLibs: { $path: "libs" },
82
+ },
83
+ StarterPlayer: {
84
+ $className: "StarterPlayer",
85
+ StarterPlayerScripts: {
86
+ $className: "StarterPlayerScripts",
87
+ },
88
+ },
89
+ HttpService: {
90
+ $className: "HttpService",
91
+ $properties: {
92
+ HttpEnabled: true,
93
+ },
94
+ },
95
+ };
96
+ }
97
+
98
+ export function buildRojoTree(root: string, rootDir: string, outDir: string): RojoNode {
99
+ const outRoot = path.join(root, outDir);
100
+ const srcRoot = path.join(root, rootDir);
101
+ const sourceRoot = fs.existsSync(outRoot) ? outRoot : srcRoot;
102
+ const tree = baseTree();
103
+ const relRoot = path.relative(root, sourceRoot).replace(/\\/g, "/");
104
+
105
+ withPath(ensureNode(tree, ["ServerScriptService"]), `${relRoot}/Server`);
106
+ withPath(ensureNode(tree, ["ServerScriptService", "Parallel"]), `${relRoot}/Parallel`);
107
+ withPath(ensureNode(tree, ["StarterPlayer", "StarterPlayerScripts"]), `${relRoot}/Client`);
108
+ withPath(ensureNode(tree, ["ReplicatedStorage", "Declarations"]), `${relRoot}/Declarations`);
109
+ withPath(ensureNode(tree, ["ReplicatedStorage", "Include"]), `${relRoot}/Include`);
110
+
111
+ mapModules(tree, root, path.join(sourceRoot, "Modules"));
112
+ return tree;
113
+ }
114
+
115
+ export function writeDefaultProject(root: string, rootDir: string, outDir: string, projectJsonPath?: string): string {
116
+ const file = path.resolve(root, projectJsonPath || "default.project.json");
117
+ const body = {
118
+ name: "cluaupp-game",
119
+ tree: buildRojoTree(root, rootDir, outDir),
120
+ };
121
+ fs.writeFileSync(file, `${JSON.stringify(body, null, "\t")}\n`, "utf8");
122
+ return file;
123
+ }
@@ -19,6 +19,7 @@ import { checkFlareVersions } from "../target/flare-version.js";
19
19
  import { checkComponentContracts } from "../target/component-contracts.js";
20
20
  import { loadPlatformPolicy } from "../target/authority-check.js";
21
21
  import { buildDatamodelProfile } from "../target/datamodel.js";
22
+ import { writeDefaultProject } from "../target/gen-rojo-tree.js";
22
23
  import {
23
24
  defaultJobCount,
24
25
  hashText,
@@ -315,6 +316,10 @@ function createMapper(root: string, config: ProjectConfig, rojoPath?: string): R
315
316
  return mapper;
316
317
  }
317
318
 
319
+ function syncRojoTree(root: string, config: ProjectConfig, rojoPath?: string): void {
320
+ writeDefaultProject(root, config.rootDir, config.outDir, rojoPath || "default.project.json");
321
+ }
322
+
318
323
  function compileOptions(root: string, config: ProjectConfig, file: string, rel: string) {
319
324
  const srcDir = path.join(root, config.rootDir);
320
325
  return {
@@ -609,6 +614,7 @@ function finishBuild(
609
614
  }
610
615
 
611
616
  const written = writeJobs(root, config, compiled.jobs, format);
617
+ syncRojoTree(root, config, options.rojo);
612
618
  try {
613
619
  const soaPlans = collectSoaPlansFromProject(root, config.rootDir);
614
620
  if (soaPlans.length) {
@@ -649,6 +655,7 @@ function prepareBuild(root: string, options: BuildOptions) {
649
655
  const exitOnError = options.exitOnError !== false;
650
656
  const holdOnError = options.holdOnError === true;
651
657
  const config = loadConfig(root);
658
+ syncRojoTree(root, config, options.rojo);
652
659
  if (options.strict === true) {
653
660
  config.strict = true;
654
661
  }
@@ -728,6 +735,8 @@ export async function init(dest: string): Promise<void> {
728
735
  copyDir(skills, path.join(target, ".cursor", "skills"));
729
736
  }
730
737
  copyRuntime(target);
738
+ const initConfig = loadConfig(target);
739
+ syncRojoTree(target, initConfig);
731
740
  syncEditorSupport(target);
732
741
  try {
733
742
  installEditorExtension();
@@ -1,5 +1,5 @@
1
1
  {
2
- "rootDir": "src",
2
+ "rootDir": "Src",
3
3
  "outDir": "out",
4
4
  "strict": false,
5
5
  "architecture": false
@@ -2,18 +2,23 @@
2
2
  "name": "cluaupp-game",
3
3
  "tree": {
4
4
  "$className": "DataModel",
5
- "ReplicatedFirst": {
6
- "$className": "ReplicatedFirst",
7
- "$path": "out/ReplicatedFirst"
8
- },
9
5
  "ServerScriptService": {
10
6
  "$className": "ServerScriptService",
11
- "$path": "out/ServerScriptService"
7
+ "$path": "out/Server",
8
+ "Parallel": {
9
+ "$path": "out/Parallel"
10
+ }
12
11
  },
13
12
  "ReplicatedStorage": {
14
13
  "$className": "ReplicatedStorage",
15
- "Shared": {
16
- "$path": "out/ReplicatedStorage/Shared"
14
+ "Declarations": {
15
+ "$path": "out/Declarations"
16
+ },
17
+ "Include": {
18
+ "$path": "out/Include"
19
+ },
20
+ "Modules": {
21
+ "$path": "out/Modules"
17
22
  },
18
23
  "CluauppLibs": {
19
24
  "$path": "libs"
@@ -23,17 +28,9 @@
23
28
  "$className": "StarterPlayer",
24
29
  "StarterPlayerScripts": {
25
30
  "$className": "StarterPlayerScripts",
26
- "$path": "out/StarterPlayer/StarterPlayerScripts"
27
- },
28
- "StarterCharacterScripts": {
29
- "$className": "StarterCharacterScripts",
30
- "$path": "out/StarterPlayer/StarterCharacterScripts"
31
+ "$path": "out/Client"
31
32
  }
32
33
  },
33
- "ServerStorage": {
34
- "$className": "ServerStorage",
35
- "$path": "out/ServerStorage"
36
- },
37
34
  "HttpService": {
38
35
  "$className": "HttpService",
39
36
  "$properties": {
@@ -0,0 +1,4 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+
4
+ void init() {}
@@ -1,7 +1,7 @@
1
1
  #pragma strict
2
2
  #include <clpp/roblox.clh>
3
3
  #include <clpp/libs/keep.clh>
4
- import { PlayerTemplate } from "../../ReplicatedStorage/Shared/Constants/Datas/TemplateData.clh";
4
+ import { PlayerTemplate } from "../../Include/GameTypes.clh";
5
5
 
6
6
  void init() {
7
7
  PlayerTemplate playerData = PlayerTemplate();
@@ -0,0 +1,4 @@
1
+ #pragma strict
2
+ #include <clpp/roblox.clh>
3
+
4
+ void init() {}
@@ -1,26 +0,0 @@
1
- #pragma once
2
- // cluaupp generated — do not edit. Change the .flare schema and run cluaupp build.
3
- // Generated by Cluaupp Flare from ReplicatedStorage/Shared/Net/Net.flare
4
- // Tag + params in the .flare file. This header is IntelliSense; runtime is the generated .luau.
5
-
6
- struct NetReady {
7
- void FireServer();
8
- RBXScriptConnection Connect(func fn);
9
- };
10
-
11
- struct NetWelcome {
12
- void Fire(Player player, int userId, double clock);
13
- void FireAll(int userId, double clock);
14
- RBXScriptConnection Connect(func fn);
15
- };
16
-
17
- struct NetSession {
18
- int Invoke();
19
- void On(func fn);
20
- };
21
-
22
- struct Net {
23
- NetReady Ready;
24
- NetWelcome Welcome;
25
- NetSession Session;
26
- };
@@ -1,4 +0,0 @@
1
- #pragma once
2
-
3
- const string STORE_NAME = "PlayerData";
4
- const bool USE_MOCK_IN_STUDIO = true;
@@ -1,6 +0,0 @@
1
- #pragma strict
2
- #include <clpp/roblox.clh>
3
-
4
- void init() {
5
- post("character local ready");
6
- }
@@ -1,4 +0,0 @@
1
- #pragma once
2
-
3
- const string STORE_NAME = "PlayerData";
4
- const bool USE_MOCK_IN_STUDIO = true;
@@ -1,6 +0,0 @@
1
- #pragma strict
2
- #include <clpp/roblox.clh>
3
-
4
- void init() {
5
- post("character local ready");
6
- }