@erik9994857/cag 1.0.2 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erik9994857/cag",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "CaG — A code library and custom language for building 3D worlds with .cagc files, .bbmodel support, and auto UV mapping",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  "node": ">=18.0.0"
32
32
  },
33
33
  "dependencies": {
34
- "pkg": "^5.8.1"
34
+ "@electron/packager": "^18.3.0"
35
35
  },
36
36
  "devDependencies": {}
37
37
  }
@@ -7,7 +7,7 @@ function ExeBuilder(engine) {
7
7
  this.info = engine.getInfo();
8
8
  this.projectRoot = engine.projectRoot;
9
9
  this.outputDir = path.join(this.projectRoot, "dist");
10
- this.tempDir = path.join(this.outputDir, ".build-temp");
10
+ this.tempDir = path.join(this.outputDir, ".cag-build");
11
11
  this.projectName = this.info.ID.split(".")[1] || this.info.ID.split(".")[0] || "cag-app";
12
12
  }
13
13
 
@@ -15,78 +15,66 @@ ExeBuilder.prototype.build = function (options) {
15
15
  options = options || {};
16
16
  var platform = options.platform || this.detectPlatform();
17
17
  var arch = options.arch || "x64";
18
- var nodeVersion = options.nodeVersion || "node18";
18
+ var ePlatform = this.mapPlatform(platform);
19
19
 
20
20
  this.ensureDirectories();
21
- this.ensurePkgInstalled();
21
+ this.generateElectronApp();
22
+ this.installElectron();
23
+ this.runPackager(ePlatform, arch);
22
24
 
23
- var entryFile = this.generateEntryPoint();
24
- var packageFile = this.generatePackageJson();
25
+ var folderName = this.projectName + "-" + ePlatform + "-" + arch;
26
+ var folder = path.join(this.outputDir, folderName);
27
+ var exeName = this.projectName + (platform === "win" ? ".exe" : "");
28
+ var exePath = path.join(folder, exeName);
25
29
 
26
- var target = nodeVersion + "-" + platform + "-" + arch;
27
- var outputName = this.projectName;
28
-
29
- if (platform === "win") {
30
- outputName += ".exe";
31
- } else if (platform === "macos") {
32
- outputName += ".app";
33
- }
34
-
35
- var outputPath = path.join(this.outputDir, outputName);
36
-
37
- this.runPkg(entryFile, outputPath, target);
38
30
  this.cleanup();
39
31
 
40
32
  return {
41
- outputPath: outputPath,
42
- outputName: outputName,
33
+ outputPath: exePath,
34
+ outputDir: folder,
35
+ outputName: exeName,
43
36
  platform: platform,
44
37
  arch: arch,
45
- target: target,
46
- size: this.getFileSize(outputPath)
38
+ size: this.getFileSize(exePath),
39
+ success: true
47
40
  };
48
41
  };
49
42
 
50
43
  ExeBuilder.prototype.buildAll = function (options) {
51
44
  options = options || {};
52
- var nodeVersion = options.nodeVersion || "node18";
53
45
  var results = [];
54
-
55
46
  var targets = [
56
- { platform: "win", arch: "x64", ext: ".exe" },
57
- { platform: "macos", arch: "x64", ext: ".app" },
58
- { platform: "linux", arch: "x64", ext: "" }
47
+ { platform: "win", ePlatform: "win32", arch: "x64", ext: ".exe" },
48
+ { platform: "macos", ePlatform: "darwin", arch: "x64", ext: "" },
49
+ { platform: "linux", ePlatform: "linux", arch: "x64", ext: "" }
59
50
  ];
60
51
 
61
52
  this.ensureDirectories();
62
- this.ensurePkgInstalled();
63
-
64
- var entryFile = this.generateEntryPoint();
65
- this.generatePackageJson();
53
+ this.generateElectronApp();
54
+ this.installElectron();
66
55
 
67
56
  for (var i = 0; i < targets.length; i++) {
68
57
  var t = targets[i];
69
- var target = nodeVersion + "-" + t.platform + "-" + t.arch;
70
- var outputName = this.projectName + "-" + t.platform + "-" + t.arch + t.ext;
71
- var outputPath = path.join(this.outputDir, outputName);
72
-
73
58
  try {
74
- this.runPkg(entryFile, outputPath, target);
59
+ this.runPackager(t.ePlatform, t.arch);
60
+ var folderName = this.projectName + "-" + t.ePlatform + "-" + t.arch;
61
+ var folder = path.join(this.outputDir, folderName);
62
+ var exeName = this.projectName + t.ext;
63
+ var exePath = path.join(folder, exeName);
75
64
  results.push({
76
- outputPath: outputPath,
77
- outputName: outputName,
65
+ outputPath: exePath,
66
+ outputDir: folder,
67
+ outputName: exeName,
78
68
  platform: t.platform,
79
69
  arch: t.arch,
80
- target: target,
81
- size: this.getFileSize(outputPath),
70
+ size: this.getFileSize(exePath),
82
71
  success: true
83
72
  });
84
73
  } catch (e) {
85
74
  results.push({
86
- outputName: outputName,
75
+ outputName: this.projectName + t.ext,
87
76
  platform: t.platform,
88
77
  arch: t.arch,
89
- target: target,
90
78
  success: false,
91
79
  error: e.message
92
80
  });
@@ -98,362 +86,717 @@ ExeBuilder.prototype.buildAll = function (options) {
98
86
  };
99
87
 
100
88
  ExeBuilder.prototype.ensureDirectories = function () {
101
- if (!fs.existsSync(this.outputDir)) {
102
- fs.mkdirSync(this.outputDir, { recursive: true });
103
- }
104
- if (!fs.existsSync(this.tempDir)) {
105
- fs.mkdirSync(this.tempDir, { recursive: true });
106
- }
89
+ if (!fs.existsSync(this.outputDir)) fs.mkdirSync(this.outputDir, { recursive: true });
90
+ if (fs.existsSync(this.tempDir)) this.removeDirectory(this.tempDir);
91
+ fs.mkdirSync(this.tempDir, { recursive: true });
107
92
  };
108
93
 
109
- ExeBuilder.prototype.ensurePkgInstalled = function () {
110
- var found = this.findPkgBin();
111
- if (found !== "npx pkg") return;
94
+ ExeBuilder.prototype.generateElectronApp = function () {
95
+ fs.writeFileSync(path.join(this.tempDir, "main.js"), this.getMainProcessSource());
96
+ fs.writeFileSync(path.join(this.tempDir, "index.html"), this.getRendererSource());
97
+ var pkg = {
98
+ name: this.projectName,
99
+ version: this.info.version || "1.0.0",
100
+ main: "main.js",
101
+ dependencies: {}
102
+ };
103
+ fs.writeFileSync(path.join(this.tempDir, "package.json"), JSON.stringify(pkg, null, 2));
104
+ };
112
105
 
113
- var npxCheck = null;
114
- try {
115
- npxCheck = childProcess.execSync("npx pkg --version", { stdio: "pipe" });
116
- } catch (e) {
117
- npxCheck = null;
118
- }
106
+ ExeBuilder.prototype.installElectron = function () {
107
+ childProcess.execSync("npm install electron@latest --save --no-audit --no-fund", {
108
+ cwd: this.tempDir,
109
+ stdio: "inherit"
110
+ });
111
+ };
119
112
 
120
- if (npxCheck) return;
113
+ ExeBuilder.prototype.getMainProcessSource = function () {
114
+ var lines = [];
115
+ lines.push("var electron = require('electron');");
116
+ lines.push("var app = electron.app;");
117
+ lines.push("var BrowserWindow = electron.BrowserWindow;");
118
+ lines.push("var globalShortcut = electron.globalShortcut;");
119
+ lines.push("var path = require('path');");
120
+ lines.push("");
121
+ lines.push("var win = null;");
122
+ lines.push("");
123
+ lines.push("app.whenReady().then(function () {");
124
+ lines.push(" win = new BrowserWindow({");
125
+ lines.push(" width: 1280,");
126
+ lines.push(" height: 720,");
127
+ lines.push(" minWidth: 800,");
128
+ lines.push(" minHeight: 600,");
129
+ lines.push(" title: " + JSON.stringify(this.info.ID + " - CaG Engine") + ",");
130
+ lines.push(" fullscreenable: true,");
131
+ lines.push(" webPreferences: {");
132
+ lines.push(" nodeIntegration: false,");
133
+ lines.push(" contextIsolation: true");
134
+ lines.push(" },");
135
+ lines.push(" backgroundColor: '#1a1a2e',");
136
+ lines.push(" autoHideMenuBar: true,");
137
+ lines.push(" show: false");
138
+ lines.push(" });");
139
+ lines.push(" win.setMenuBarVisibility(false);");
140
+ lines.push(" win.loadFile('index.html');");
141
+ lines.push(" win.once('ready-to-show', function () { win.show(); });");
142
+ lines.push(" win.on('closed', function () { win = null; });");
143
+ lines.push(" win.webContents.on('before-input-event', function (event, input) {");
144
+ lines.push(" if (input.key === 'F11') {");
145
+ lines.push(" win.setFullScreen(!win.isFullScreen());");
146
+ lines.push(" }");
147
+ lines.push(" });");
148
+ lines.push("});");
149
+ lines.push("");
150
+ lines.push("app.on('window-all-closed', function () { app.quit(); });");
151
+ return lines.join("\n");
152
+ };
121
153
 
122
- try {
123
- childProcess.execSync("npm install -g pkg@5.8.1", {
124
- cwd: this.projectRoot,
125
- stdio: "inherit"
126
- });
127
- } catch (e) {
128
- try {
129
- childProcess.execSync("npm install pkg@5.8.1", {
130
- cwd: this.projectRoot,
131
- stdio: "inherit"
132
- });
133
- } catch (e2) {
134
- throw new Error(
135
- "Failed to install pkg. Run manually: npm install -g pkg"
136
- );
137
- }
138
- }
154
+ ExeBuilder.prototype.getRendererSource = function () {
155
+ var blocks = this.generateWorldBlocks();
156
+ var info = this.info;
157
+
158
+ var css = [
159
+ "* { margin: 0; padding: 0; box-sizing: border-box; }",
160
+ "body { background: #1a1a2e; overflow: hidden; font-family: monospace; }",
161
+ "#loading { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #1a1a2e; display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 999; color: #fff; transition: opacity 0.5s; }",
162
+ "#loading.fade-out { opacity: 0; pointer-events: none; }",
163
+ "#loading h1 { font-size: 64px; color: #4ecca3; margin-bottom: 4px; letter-spacing: 6px; text-shadow: 0 0 30px rgba(78,204,163,0.3); }",
164
+ "#loading h2 { font-size: 14px; color: #666; margin-bottom: 30px; font-weight: normal; letter-spacing: 2px; }",
165
+ "#load-status { font-size: 12px; color: #555; margin-bottom: 12px; min-height: 18px; transition: color 0.3s; }",
166
+ "#bar-outer { width: 300px; height: 3px; background: #2a2a3e; border-radius: 2px; overflow: hidden; }",
167
+ "#bar-inner { width: 0%; height: 100%; background: linear-gradient(90deg, #4ecca3, #45b7d1); border-radius: 2px; transition: width 0.4s ease-out; }",
168
+ "#loading .version-tag { font-size: 11px; color: #444; margin-top: 20px; }",
169
+ "#click-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.65); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 998; cursor: pointer; transition: opacity 0.3s; }",
170
+ "#click-overlay:hover { background: rgba(0,0,0,0.55); }",
171
+ "#click-overlay .play-icon { width: 80px; height: 80px; border: 3px solid #4ecca3; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 16px; transition: transform 0.2s, border-color 0.2s; }",
172
+ "#click-overlay:hover .play-icon { transform: scale(1.1); border-color: #45b7d1; }",
173
+ "#click-overlay .play-triangle { width: 0; height: 0; border-style: solid; border-width: 15px 0 15px 28px; border-color: transparent transparent transparent #4ecca3; margin-left: 6px; }",
174
+ "#click-overlay span { color: #888; font-size: 16px; letter-spacing: 3px; }",
175
+ "canvas { display: block; position: fixed; top: 0; left: 0; }",
176
+ "#hud { position: fixed; top: 10px; left: 10px; z-index: 100; pointer-events: none; }",
177
+ "#hud-box { background: rgba(0,0,0,0.7); padding: 10px 14px; border-left: 3px solid #4ecca3; backdrop-filter: blur(4px); border-radius: 0 4px 4px 0; }",
178
+ "#hud-box div { color: #bbb; font-size: 11px; line-height: 17px; }",
179
+ "#hud-box .hud-title { color: #4ecca3; font-size: 13px; font-weight: bold; margin-bottom: 3px; letter-spacing: 1px; }",
180
+ "#hud-box .hud-sep { border-top: 1px solid #333; margin: 4px 0; }",
181
+ "#crosshair { position: fixed; top: 50%; left: 50%; width: 24px; height: 24px; margin: -12px 0 0 -12px; z-index: 100; pointer-events: none; }",
182
+ "#crosshair::before { content: ''; position: absolute; top: 11px; left: 3px; width: 18px; height: 2px; background: rgba(255,255,255,0.6); border-radius: 1px; }",
183
+ "#crosshair::after { content: ''; position: absolute; top: 3px; left: 11px; width: 2px; height: 18px; background: rgba(255,255,255,0.6); border-radius: 1px; }",
184
+ "#controls-hint { position: fixed; bottom: 10px; right: 10px; z-index: 100; pointer-events: none; background: rgba(0,0,0,0.55); padding: 8px 14px; color: #666; font-size: 10px; border-radius: 4px; line-height: 16px; backdrop-filter: blur(4px); }",
185
+ "#controls-hint b { color: #888; }"
186
+ ].join("\n");
187
+
188
+ var vs = [
189
+ "attribute vec3 aPos;",
190
+ "attribute vec3 aColor;",
191
+ "attribute vec3 aNormal;",
192
+ "uniform mat4 uProj;",
193
+ "uniform mat4 uView;",
194
+ "varying vec3 vColor;",
195
+ "varying vec3 vNormal;",
196
+ "varying vec3 vWorldPos;",
197
+ "void main() {",
198
+ " vColor = aColor;",
199
+ " vNormal = aNormal;",
200
+ " vWorldPos = aPos;",
201
+ " gl_Position = uProj * uView * vec4(aPos, 1.0);",
202
+ "}"
203
+ ].join("\\n");
204
+
205
+ var fs_shader = [
206
+ "precision mediump float;",
207
+ "varying vec3 vColor;",
208
+ "varying vec3 vNormal;",
209
+ "varying vec3 vWorldPos;",
210
+ "uniform vec3 uSunDir;",
211
+ "uniform vec3 uSunColor;",
212
+ "uniform vec3 uAmbient;",
213
+ "uniform vec3 uFogColor;",
214
+ "uniform float uFogNear;",
215
+ "uniform float uFogFar;",
216
+ "uniform vec3 uCamPos;",
217
+ "void main() {",
218
+ " vec3 norm = normalize(vNormal);",
219
+ " float diff = max(dot(norm, normalize(uSunDir)), 0.0);",
220
+ " vec3 lit = vColor * (uAmbient + uSunColor * diff);",
221
+ " float dist = length(vWorldPos - uCamPos);",
222
+ " float fog = clamp((dist - uFogNear) / (uFogFar - uFogNear), 0.0, 1.0);",
223
+ " vec3 final = mix(lit, uFogColor, fog);",
224
+ " gl_FragColor = vec4(final, 1.0);",
225
+ "}"
226
+ ].join("\\n");
227
+
228
+ var js = [];
229
+ js.push("var BLOCKS = " + JSON.stringify(blocks) + ";");
230
+ js.push("var INFO = " + JSON.stringify(info) + ";");
231
+ js.push("");
232
+ js.push("var VS_SRC = \"" + vs + "\";");
233
+ js.push("var FS_SRC = \"" + fs_shader + "\";");
234
+ js.push("");
235
+ js.push("var cag = {");
236
+ js.push(" gl: null, canvas: null, program: null,");
237
+ js.push(" camX: 16, camY: 12, camZ: 16,");
238
+ js.push(" pitch: -0.5, yaw: 0.8,");
239
+ js.push(" keys: {}, locked: false,");
240
+ js.push(" velY: 0, onGround: false, gravity: 0.015,");
241
+ js.push(" fps: 0, frames: 0, lastFps: 0,");
242
+ js.push(" vbo: null, vertCount: 0,");
243
+ js.push(" blockMap: {},");
244
+ js.push(" uProj: null, uView: null, uSunDir: null, uSunColor: null,");
245
+ js.push(" uAmbient: null, uFogColor: null, uFogNear: null, uFogFar: null, uCamPos: null,");
246
+ js.push("");
247
+ js.push(" init: function () {");
248
+ js.push(" this.canvas = document.getElementById('cag-canvas');");
249
+ js.push(" this.gl = this.canvas.getContext('webgl', { antialias: true });");
250
+ js.push(" if (!this.gl) { alert('WebGL not supported'); return; }");
251
+ js.push(" this.resize();");
252
+ js.push(" this.buildBlockMap();");
253
+ js.push(" this.compileShaders();");
254
+ js.push(" this.buildMesh();");
255
+ js.push(" this.bindInput();");
256
+ js.push(" var loadEl = document.getElementById('loading');");
257
+ js.push(" loadEl.classList.add('fade-out');");
258
+ js.push(" setTimeout(function () {");
259
+ js.push(" loadEl.style.display = 'none';");
260
+ js.push(" document.getElementById('click-overlay').style.display = 'flex';");
261
+ js.push(" }, 500);");
262
+ js.push(" this.lastFps = performance.now();");
263
+ js.push(" this.loop();");
264
+ js.push(" },");
265
+ js.push("");
266
+ js.push(" buildBlockMap: function () {");
267
+ js.push(" for (var i = 0; i < BLOCKS.length; i++) {");
268
+ js.push(" var b = BLOCKS[i];");
269
+ js.push(" this.blockMap[b.x + ',' + b.y + ',' + b.z] = b;");
270
+ js.push(" }");
271
+ js.push(" },");
272
+ js.push("");
273
+ js.push(" hasBlock: function (x, y, z) {");
274
+ js.push(" return this.blockMap[x + ',' + y + ',' + z] !== undefined;");
275
+ js.push(" },");
276
+ js.push("");
277
+ js.push(" compileShaders: function () {");
278
+ js.push(" var gl = this.gl;");
279
+ js.push(" var vs = gl.createShader(gl.VERTEX_SHADER);");
280
+ js.push(" gl.shaderSource(vs, VS_SRC); gl.compileShader(vs);");
281
+ js.push(" var fs = gl.createShader(gl.FRAGMENT_SHADER);");
282
+ js.push(" gl.shaderSource(fs, FS_SRC); gl.compileShader(fs);");
283
+ js.push(" this.program = gl.createProgram();");
284
+ js.push(" gl.attachShader(this.program, vs);");
285
+ js.push(" gl.attachShader(this.program, fs);");
286
+ js.push(" gl.linkProgram(this.program);");
287
+ js.push(" gl.useProgram(this.program);");
288
+ js.push(" this.uProj = gl.getUniformLocation(this.program, 'uProj');");
289
+ js.push(" this.uView = gl.getUniformLocation(this.program, 'uView');");
290
+ js.push(" this.uSunDir = gl.getUniformLocation(this.program, 'uSunDir');");
291
+ js.push(" this.uSunColor = gl.getUniformLocation(this.program, 'uSunColor');");
292
+ js.push(" this.uAmbient = gl.getUniformLocation(this.program, 'uAmbient');");
293
+ js.push(" this.uFogColor = gl.getUniformLocation(this.program, 'uFogColor');");
294
+ js.push(" this.uFogNear = gl.getUniformLocation(this.program, 'uFogNear');");
295
+ js.push(" this.uFogFar = gl.getUniformLocation(this.program, 'uFogFar');");
296
+ js.push(" this.uCamPos = gl.getUniformLocation(this.program, 'uCamPos');");
297
+ js.push(" gl.uniform3f(this.uSunDir, 0.4, 0.8, 0.3);");
298
+ js.push(" gl.uniform3f(this.uSunColor, 1.0, 0.95, 0.85);");
299
+ js.push(" gl.uniform3f(this.uAmbient, 0.35, 0.38, 0.5);");
300
+ js.push(" gl.uniform3f(this.uFogColor, 0.53, 0.81, 0.92);");
301
+ js.push(" gl.uniform1f(this.uFogNear, 30.0);");
302
+ js.push(" gl.uniform1f(this.uFogFar, 70.0);");
303
+ js.push(" },");
304
+ js.push("");
305
+ js.push(" getBlockColor: function (b, face) {");
306
+ js.push(" var r, g, bl;");
307
+ js.push(" if (b.t === 'grass') {");
308
+ js.push(" if (face === 'top') { r = 0.34; g = 0.68; bl = 0.24; }");
309
+ js.push(" else if (face === 'bottom') { r = 0.55; g = 0.38; bl = 0.18; }");
310
+ js.push(" else { r = 0.42; g = 0.50; bl = 0.22; }");
311
+ js.push(" } else if (b.t === 'dirt') {");
312
+ js.push(" r = 0.55; g = 0.38; bl = 0.18;");
313
+ js.push(" } else if (b.t === 'stone') {");
314
+ js.push(" if (face === 'top') { r = 0.58; g = 0.58; bl = 0.58; }");
315
+ js.push(" else { r = 0.50; g = 0.50; bl = 0.50; }");
316
+ js.push(" } else if (b.t === 'sand') {");
317
+ js.push(" if (face === 'top') { r = 0.86; g = 0.82; bl = 0.58; }");
318
+ js.push(" else { r = 0.80; g = 0.76; bl = 0.52; }");
319
+ js.push(" } else if (b.t === 'water') {");
320
+ js.push(" if (face === 'top') { r = 0.15; g = 0.45; bl = 0.75; }");
321
+ js.push(" else { r = 0.10; g = 0.35; bl = 0.65; }");
322
+ js.push(" } else if (b.t === 'snow') {");
323
+ js.push(" if (face === 'top') { r = 0.95; g = 0.96; bl = 0.98; }");
324
+ js.push(" else { r = 0.88; g = 0.90; bl = 0.92; }");
325
+ js.push(" } else if (b.t === 'wood' || b.t === 'log') {");
326
+ js.push(" if (face === 'top' || face === 'bottom') { r = 0.62; g = 0.52; bl = 0.30; }");
327
+ js.push(" else { r = 0.45; g = 0.32; bl = 0.18; }");
328
+ js.push(" } else if (b.t === 'leaf' || b.t === 'leaves') {");
329
+ js.push(" r = 0.20; g = 0.55; bl = 0.15;");
330
+ js.push(" } else if (b.t === 'planks') {");
331
+ js.push(" r = 0.72; g = 0.58; bl = 0.35;");
332
+ js.push(" } else if (b.t === 'cobblestone' || b.t === 'cobble') {");
333
+ js.push(" if (face === 'top') { r = 0.52; g = 0.52; bl = 0.52; }");
334
+ js.push(" else { r = 0.44; g = 0.44; bl = 0.44; }");
335
+ js.push(" } else if (b.t === 'gravel') {");
336
+ js.push(" r = 0.56; g = 0.54; bl = 0.50;");
337
+ js.push(" } else if (b.t === 'clay') {");
338
+ js.push(" r = 0.62; g = 0.60; bl = 0.58;");
339
+ js.push(" } else if (b.t === 'iron' || b.t === 'ore') {");
340
+ js.push(" r = 0.65; g = 0.60; bl = 0.55;");
341
+ js.push(" } else if (b.t === 'gold') {");
342
+ js.push(" r = 0.90; g = 0.78; bl = 0.20;");
343
+ js.push(" } else if (b.t === 'diamond') {");
344
+ js.push(" r = 0.30; g = 0.85; bl = 0.88;");
345
+ js.push(" } else if (b.t === 'lava') {");
346
+ js.push(" r = 0.95; g = 0.35; bl = 0.05;");
347
+ js.push(" } else if (b.t === 'brick') {");
348
+ js.push(" r = 0.65; g = 0.32; bl = 0.25;");
349
+ js.push(" } else {");
350
+ js.push(" var hash = 0;");
351
+ js.push(" for (var ci = 0; ci < b.t.length; ci++) hash = ((hash << 5) - hash) + b.t.charCodeAt(ci);");
352
+ js.push(" r = 0.3 + (((hash & 0xFF) / 255) * 0.5);");
353
+ js.push(" g = 0.3 + ((((hash >> 8) & 0xFF) / 255) * 0.5);");
354
+ js.push(" bl = 0.3 + ((((hash >> 16) & 0xFF) / 255) * 0.5);");
355
+ js.push(" }");
356
+ js.push(" var v = 0.85 + (b.y / 12.0) * 0.15;");
357
+ js.push(" return [r * v, g * v, bl * v];");
358
+ js.push(" },");
359
+ js.push("");
360
+ js.push(" buildMesh: function () {");
361
+ js.push(" var verts = [];");
362
+ js.push(" var self = this;");
363
+ js.push(" function quad(x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, nx,ny,nz, c) {");
364
+ js.push(" verts.push(x1,y1,z1, c[0],c[1],c[2], nx,ny,nz);");
365
+ js.push(" verts.push(x2,y2,z2, c[0],c[1],c[2], nx,ny,nz);");
366
+ js.push(" verts.push(x3,y3,z3, c[0],c[1],c[2], nx,ny,nz);");
367
+ js.push(" verts.push(x1,y1,z1, c[0],c[1],c[2], nx,ny,nz);");
368
+ js.push(" verts.push(x3,y3,z3, c[0],c[1],c[2], nx,ny,nz);");
369
+ js.push(" verts.push(x4,y4,z4, c[0],c[1],c[2], nx,ny,nz);");
370
+ js.push(" }");
371
+ js.push(" for (var i = 0; i < BLOCKS.length; i++) {");
372
+ js.push(" var b = BLOCKS[i];");
373
+ js.push(" var x = b.x, y = b.y, z = b.z;");
374
+ js.push(" if (!self.hasBlock(x, y+1, z)) {");
375
+ js.push(" var ct = self.getBlockColor(b, 'top');");
376
+ js.push(" quad(x,y+1,z, x+1,y+1,z, x+1,y+1,z+1, x,y+1,z+1, 0,1,0, ct);");
377
+ js.push(" }");
378
+ js.push(" if (!self.hasBlock(x, y-1, z)) {");
379
+ js.push(" var cb = self.getBlockColor(b, 'bottom');");
380
+ js.push(" quad(x,y,z+1, x+1,y,z+1, x+1,y,z, x,y,z, 0,-1,0, cb);");
381
+ js.push(" }");
382
+ js.push(" if (!self.hasBlock(x, y, z-1)) {");
383
+ js.push(" var cn = self.getBlockColor(b, 'side');");
384
+ js.push(" quad(x,y,z, x+1,y,z, x+1,y+1,z, x,y+1,z, 0,0,-1, cn);");
385
+ js.push(" }");
386
+ js.push(" if (!self.hasBlock(x, y, z+1)) {");
387
+ js.push(" var cs = self.getBlockColor(b, 'side');");
388
+ js.push(" quad(x+1,y,z+1, x,y,z+1, x,y+1,z+1, x+1,y+1,z+1, 0,0,1, cs);");
389
+ js.push(" }");
390
+ js.push(" if (!self.hasBlock(x-1, y, z)) {");
391
+ js.push(" var cw = self.getBlockColor(b, 'side');");
392
+ js.push(" quad(x,y,z+1, x,y,z, x,y+1,z, x,y+1,z+1, -1,0,0, cw);");
393
+ js.push(" }");
394
+ js.push(" if (!self.hasBlock(x+1, y, z)) {");
395
+ js.push(" var ce = self.getBlockColor(b, 'side');");
396
+ js.push(" quad(x+1,y,z, x+1,y,z+1, x+1,y+1,z+1, x+1,y+1,z, 1,0,0, ce);");
397
+ js.push(" }");
398
+ js.push(" }");
399
+ js.push(" this.vertCount = verts.length / 9;");
400
+ js.push(" var gl = this.gl;");
401
+ js.push(" this.vbo = gl.createBuffer();");
402
+ js.push(" gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);");
403
+ js.push(" gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);");
404
+ js.push(" var aPos = gl.getAttribLocation(this.program, 'aPos');");
405
+ js.push(" var aColor = gl.getAttribLocation(this.program, 'aColor');");
406
+ js.push(" var aNormal = gl.getAttribLocation(this.program, 'aNormal');");
407
+ js.push(" gl.enableVertexAttribArray(aPos);");
408
+ js.push(" gl.enableVertexAttribArray(aColor);");
409
+ js.push(" gl.enableVertexAttribArray(aNormal);");
410
+ js.push(" gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 36, 0);");
411
+ js.push(" gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 36, 12);");
412
+ js.push(" gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, 36, 24);");
413
+ js.push(" },");
414
+ js.push("");
415
+ js.push(" resize: function () {");
416
+ js.push(" this.canvas.width = window.innerWidth;");
417
+ js.push(" this.canvas.height = window.innerHeight;");
418
+ js.push(" if (this.gl) this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);");
419
+ js.push(" },");
420
+ js.push("");
421
+ js.push(" bindInput: function () {");
422
+ js.push(" var self = this;");
423
+ js.push(" document.addEventListener('keydown', function (e) { self.keys[e.code] = true; });");
424
+ js.push(" document.addEventListener('keyup', function (e) { self.keys[e.code] = false; });");
425
+ js.push(" window.addEventListener('resize', function () { self.resize(); });");
426
+ js.push(" document.addEventListener('mousemove', function (e) {");
427
+ js.push(" if (!self.locked) return;");
428
+ js.push(" self.yaw += e.movementX * 0.003;");
429
+ js.push(" self.pitch -= e.movementY * 0.003;");
430
+ js.push(" if (self.pitch > 1.5) self.pitch = 1.5;");
431
+ js.push(" if (self.pitch < -1.5) self.pitch = -1.5;");
432
+ js.push(" });");
433
+ js.push(" document.addEventListener('pointerlockchange', function () {");
434
+ js.push(" self.locked = document.pointerLockElement === self.canvas;");
435
+ js.push(" var ov = document.getElementById('click-overlay');");
436
+ js.push(" ov.style.display = self.locked ? 'none' : 'flex';");
437
+ js.push(" });");
438
+ js.push(" document.getElementById('click-overlay').addEventListener('click', function () {");
439
+ js.push(" self.canvas.requestPointerLock();");
440
+ js.push(" });");
441
+ js.push(" },");
442
+ js.push("");
443
+ js.push(" getGroundY: function (x, z) {");
444
+ js.push(" var bx = Math.floor(x);");
445
+ js.push(" var bz = Math.floor(z);");
446
+ js.push(" for (var y = 30; y >= 0; y--) {");
447
+ js.push(" if (this.hasBlock(bx, y, bz)) return y + 1;");
448
+ js.push(" }");
449
+ js.push(" return 1;");
450
+ js.push(" },");
451
+ js.push("");
452
+ js.push(" update: function () {");
453
+ js.push(" if (!this.locked) return;");
454
+ js.push(" var spd = 0.08;");
455
+ js.push(" if (this.keys['ShiftLeft'] || this.keys['ShiftRight']) spd = 0.16;");
456
+ js.push(" var dx = 0, dz = 0;");
457
+ js.push(" var sy = Math.sin(this.yaw), cy = Math.cos(this.yaw);");
458
+ js.push(" if (this.keys['KeyW'] || this.keys['ArrowUp']) { dx -= sy * spd; dz -= cy * spd; }");
459
+ js.push(" if (this.keys['KeyS'] || this.keys['ArrowDown']) { dx += sy * spd; dz += cy * spd; }");
460
+ js.push(" if (this.keys['KeyA'] || this.keys['ArrowLeft']) { dx -= cy * spd; dz += sy * spd; }");
461
+ js.push(" if (this.keys['KeyD'] || this.keys['ArrowRight']) { dx += cy * spd; dz -= sy * spd; }");
462
+ js.push(" var nx = this.camX + dx;");
463
+ js.push(" var nz = this.camZ + dz;");
464
+ js.push(" var feet = Math.floor(this.camY - 1.6);");
465
+ js.push(" var bnx = Math.floor(nx);");
466
+ js.push(" var bnz = Math.floor(nz);");
467
+ js.push(" if (!this.hasBlock(bnx, feet, Math.floor(this.camZ)) && !this.hasBlock(bnx, feet+1, Math.floor(this.camZ))) {");
468
+ js.push(" this.camX = nx;");
469
+ js.push(" }");
470
+ js.push(" if (!this.hasBlock(Math.floor(this.camX), feet, bnz) && !this.hasBlock(Math.floor(this.camX), feet+1, bnz)) {");
471
+ js.push(" this.camZ = nz;");
472
+ js.push(" }");
473
+ js.push(" this.velY -= this.gravity;");
474
+ js.push(" this.camY += this.velY;");
475
+ js.push(" var gy = this.getGroundY(this.camX, this.camZ) + 1.6;");
476
+ js.push(" if (this.camY <= gy) {");
477
+ js.push(" this.camY = gy;");
478
+ js.push(" this.velY = 0;");
479
+ js.push(" this.onGround = true;");
480
+ js.push(" } else {");
481
+ js.push(" this.onGround = false;");
482
+ js.push(" }");
483
+ js.push(" if (this.keys['Space'] && this.onGround) {");
484
+ js.push(" this.velY = 0.18;");
485
+ js.push(" this.onGround = false;");
486
+ js.push(" }");
487
+ js.push(" },");
488
+ js.push("");
489
+ js.push(" perspective: function (fov, aspect, near, far) {");
490
+ js.push(" var f = 1.0 / Math.tan(fov / 2);");
491
+ js.push(" var nf = 1.0 / (near - far);");
492
+ js.push(" return new Float32Array([");
493
+ js.push(" f/aspect, 0, 0, 0,");
494
+ js.push(" 0, f, 0, 0,");
495
+ js.push(" 0, 0, (far+near)*nf, -1,");
496
+ js.push(" 0, 0, 2*far*near*nf, 0");
497
+ js.push(" ]);");
498
+ js.push(" },");
499
+ js.push("");
500
+ js.push(" lookAt: function () {");
501
+ js.push(" var cp = Math.cos(this.pitch), sp = Math.sin(this.pitch);");
502
+ js.push(" var cy = Math.cos(this.yaw), sy = Math.sin(this.yaw);");
503
+ js.push(" var fx = -sy * cp, fy = sp, fz = -cy * cp;");
504
+ js.push(" var len = Math.sqrt(fx*fx+fy*fy+fz*fz);");
505
+ js.push(" fx/=len; fy/=len; fz/=len;");
506
+ js.push(" var ux = 0, uy = 1, uz = 0;");
507
+ js.push(" var rx = fy*uz - fz*uy, ry = fz*ux - fx*uz, rz = fx*uy - fy*ux;");
508
+ js.push(" len = Math.sqrt(rx*rx+ry*ry+rz*rz);");
509
+ js.push(" rx/=len; ry/=len; rz/=len;");
510
+ js.push(" ux = ry*fz - rz*fy; uy = rz*fx - rx*fz; uz = rx*fy - ry*fx;");
511
+ js.push(" var tx = -rx*this.camX - ry*this.camY - rz*this.camZ;");
512
+ js.push(" var ty = -ux*this.camX - uy*this.camY - uz*this.camZ;");
513
+ js.push(" var tz = fx*this.camX + fy*this.camY + fz*this.camZ;");
514
+ js.push(" return new Float32Array([");
515
+ js.push(" rx, ux, -fx, 0,");
516
+ js.push(" ry, uy, -fy, 0,");
517
+ js.push(" rz, uz, -fz, 0,");
518
+ js.push(" tx, ty, tz, 1");
519
+ js.push(" ]);");
520
+ js.push(" },");
521
+ js.push("");
522
+ js.push(" render: function () {");
523
+ js.push(" var gl = this.gl;");
524
+ js.push(" gl.clearColor(0.53, 0.81, 0.92, 1.0);");
525
+ js.push(" gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);");
526
+ js.push(" gl.enable(gl.DEPTH_TEST);");
527
+ js.push(" gl.enable(gl.CULL_FACE);");
528
+ js.push(" gl.cullFace(gl.BACK);");
529
+ js.push(" var aspect = this.canvas.width / this.canvas.height;");
530
+ js.push(" var proj = this.perspective(1.2, aspect, 0.1, 200.0);");
531
+ js.push(" var view = this.lookAt();");
532
+ js.push(" gl.uniformMatrix4fv(this.uProj, false, proj);");
533
+ js.push(" gl.uniformMatrix4fv(this.uView, false, view);");
534
+ js.push(" gl.uniform3f(this.uCamPos, this.camX, this.camY, this.camZ);");
535
+ js.push(" gl.drawArrays(gl.TRIANGLES, 0, this.vertCount);");
536
+ js.push(" this.updateHUD();");
537
+ js.push(" },");
538
+ js.push("");
539
+ js.push(" getStandingBlock: function () {");
540
+ js.push(" var bx = Math.floor(this.camX);");
541
+ js.push(" var bz = Math.floor(this.camZ);");
542
+ js.push(" var by = Math.floor(this.camY - 1.7);");
543
+ js.push(" var b = this.blockMap[bx + ',' + by + ',' + bz];");
544
+ js.push(" return b ? b.t : 'air';");
545
+ js.push(" },");
546
+ js.push("");
547
+ js.push(" updateHUD: function () {");
548
+ js.push(" var h = document.getElementById('hud-info');");
549
+ js.push(" if (!h) return;");
550
+ js.push(" var standing = this.getStandingBlock();");
551
+ js.push(" var sprinting = this.keys['ShiftLeft'] || this.keys['ShiftRight'];");
552
+ js.push(" var tris = Math.floor(this.vertCount / 3);");
553
+ js.push(" h.innerHTML = '<div class=\"hud-title\">CaG Engine</div>' +");
554
+ js.push(" '<div>' + INFO.ID + ' v' + INFO.version + '</div>' +");
555
+ js.push(" '<div class=\"hud-sep\"></div>' +");
556
+ js.push(" '<div>FPS: ' + this.fps + ' | Tris: ' + tris.toLocaleString() + '</div>' +");
557
+ js.push(" '<div>Blocks: ' + BLOCKS.length.toLocaleString() + '</div>' +");
558
+ js.push(" '<div class=\"hud-sep\"></div>' +");
559
+ js.push(" '<div>X: ' + this.camX.toFixed(1) + ' Y: ' + this.camY.toFixed(1) + ' Z: ' + this.camZ.toFixed(1) + '</div>' +");
560
+ js.push(" '<div>Standing: ' + standing + (sprinting ? ' [SPRINT]' : '') + '</div>';");
561
+ js.push(" },");
562
+ js.push("");
563
+ js.push(" loop: function () {");
564
+ js.push(" this.update();");
565
+ js.push(" this.render();");
566
+ js.push(" this.frames++;");
567
+ js.push(" var now = performance.now();");
568
+ js.push(" if (now - this.lastFps >= 1000) {");
569
+ js.push(" this.fps = this.frames;");
570
+ js.push(" this.frames = 0;");
571
+ js.push(" this.lastFps = now;");
572
+ js.push(" }");
573
+ js.push(" requestAnimationFrame(this.loop.bind(this));");
574
+ js.push(" }");
575
+ js.push("};");
576
+ js.push("");
577
+ js.push("var bar = document.getElementById('bar-inner');");
578
+ js.push("var status = document.getElementById('load-status');");
579
+ js.push("bar.style.width = '10%';");
580
+ js.push("status.textContent = 'Initializing CaG Engine...';");
581
+ js.push("setTimeout(function () {");
582
+ js.push(" bar.style.width = '25%';");
583
+ js.push(" status.textContent = 'Parsing project data...';");
584
+ js.push("}, 300);");
585
+ js.push("setTimeout(function () {");
586
+ js.push(" bar.style.width = '45%';");
587
+ js.push(" status.textContent = 'Generating terrain (' + BLOCKS.length.toLocaleString() + ' blocks)...';");
588
+ js.push("}, 600);");
589
+ js.push("setTimeout(function () {");
590
+ js.push(" bar.style.width = '65%';");
591
+ js.push(" status.textContent = 'Building mesh geometry...';");
592
+ js.push("}, 900);");
593
+ js.push("setTimeout(function () {");
594
+ js.push(" bar.style.width = '80%';");
595
+ js.push(" status.textContent = 'Compiling CaG shaders...';");
596
+ js.push("}, 1200);");
597
+ js.push("setTimeout(function () {");
598
+ js.push(" bar.style.width = '95%';");
599
+ js.push(" status.textContent = 'Preparing renderer...';");
600
+ js.push("}, 1500);");
601
+ js.push("setTimeout(function () {");
602
+ js.push(" bar.style.width = '100%';");
603
+ js.push(" status.textContent = 'Ready';");
604
+ js.push(" status.style.color = '#4ecca3';");
605
+ js.push("}, 1800);");
606
+ js.push("setTimeout(function () { cag.init(); }, 2200);");
607
+
608
+ var html = "<!DOCTYPE html>\n<html>\n<head>\n";
609
+ html += "<meta charset='utf-8'>\n";
610
+ html += "<title>" + info.ID + " - CaG Engine</title>\n";
611
+ html += "<style>\n" + css + "\n</style>\n";
612
+ html += "</head>\n<body>\n";
613
+ html += "<div id='loading'>\n";
614
+ html += " <h1>CaG</h1>\n";
615
+ html += " <h2>" + info.ID + "</h2>\n";
616
+ html += " <div id='load-status'>Starting...</div>\n";
617
+ html += " <div id='bar-outer'><div id='bar-inner'></div></div>\n";
618
+ html += " <div class='version-tag'>v" + (info.version || "1.0.0") + "</div>\n";
619
+ html += "</div>\n";
620
+ html += "<div id='click-overlay' style='display:none'><div class='play-icon'><div class='play-triangle'></div></div><span>CLICK TO PLAY</span></div>\n";
621
+ html += "<div id='crosshair'></div>\n";
622
+ html += "<div id='hud'><div id='hud-box'><div id='hud-info'></div></div></div>\n";
623
+ html += "<div id='controls-hint'><b>WASD</b> Move &nbsp; <b>Mouse</b> Look &nbsp; <b>Space</b> Jump &nbsp; <b>Shift</b> Sprint &nbsp; <b>F11</b> Fullscreen &nbsp; <b>Esc</b> Release</div>\n";
624
+ html += "<canvas id='cag-canvas'></canvas>\n";
625
+ html += "<script>\n" + js.join("\n") + "\n</script>\n";
626
+ html += "</body>\n</html>";
627
+
628
+ return html;
139
629
  };
140
630
 
141
- ExeBuilder.prototype.generateEntryPoint = function () {
631
+ ExeBuilder.prototype.generateWorldBlocks = function () {
142
632
  var codeFiles = this.engine.getCodeFiles();
143
- var resourceMap = this.engine.getResourceMap();
144
- var dependencies = this.engine.getDependencies();
633
+ var topLayer = "grass";
634
+ var fillLayer = "dirt";
635
+ var bottomLayer = "stone";
636
+ var size = 32;
637
+ var seed = 54321;
638
+ var waterLevel = 3;
639
+ var hasWater = false;
145
640
 
146
- var embeddedCode = {};
147
641
  for (var i = 0; i < codeFiles.length; i++) {
148
- var fileName = path.basename(codeFiles[i]);
149
642
  var content = fs.readFileSync(codeFiles[i], "utf-8");
150
- embeddedCode[fileName] = content;
151
- }
152
-
153
- var embeddedResources = {};
154
- var resourceNames = Object.keys(resourceMap);
155
- for (var j = 0; j < resourceNames.length; j++) {
156
- var name = resourceNames[j];
157
- var res = resourceMap[name];
158
- var entry = { name: name, paired: res.paired, modelData: null, textureData: null };
159
-
160
- if (res.model && fs.existsSync(res.model)) {
161
- try {
162
- entry.modelData = JSON.parse(fs.readFileSync(res.model, "utf-8"));
163
- } catch (e) {
164
- entry.modelData = null;
643
+ var lines = content.split("\n");
644
+ for (var j = 0; j < lines.length; j++) {
645
+ var line = lines[j].trim();
646
+ if (line.indexOf("top") !== -1 && line.indexOf("layer") !== -1 && line.indexOf("=") !== -1) {
647
+ var eqIdx = line.lastIndexOf("=");
648
+ var val = line.substring(eqIdx + 1).trim();
649
+ if (val) topLayer = val.toLowerCase();
650
+ }
651
+ if (line.indexOf("fill") !== -1 && line.indexOf("layer") !== -1 && line.indexOf("=") !== -1) {
652
+ var fIdx = line.lastIndexOf("=");
653
+ var fVal = line.substring(fIdx + 1).trim();
654
+ if (fVal) fillLayer = fVal.toLowerCase();
655
+ }
656
+ if (line.indexOf("bottom") !== -1 && line.indexOf("layer") !== -1 && line.indexOf("=") !== -1) {
657
+ var bIdx = line.lastIndexOf("=");
658
+ var bVal = line.substring(bIdx + 1).trim();
659
+ if (bVal) bottomLayer = bVal.toLowerCase();
660
+ }
661
+ if (line.indexOf("water") !== -1) {
662
+ hasWater = true;
663
+ }
664
+ if (line.indexOf("size") !== -1 && line.indexOf("=") !== -1) {
665
+ var sIdx = line.lastIndexOf("=");
666
+ var sVal = parseInt(line.substring(sIdx + 1).trim(), 10);
667
+ if (!isNaN(sVal) && sVal >= 8 && sVal <= 128) size = sVal;
668
+ }
669
+ if (line.indexOf("seed") !== -1 && line.indexOf("=") !== -1) {
670
+ var sdIdx = line.lastIndexOf("=");
671
+ var sdVal = parseInt(line.substring(sdIdx + 1).trim(), 10);
672
+ if (!isNaN(sdVal)) seed = sdVal;
165
673
  }
166
674
  }
167
-
168
- if (res.texture && fs.existsSync(res.texture)) {
169
- entry.textureData = fs.readFileSync(res.texture).toString("base64");
170
- entry.textureExt = path.extname(res.texture).toLowerCase();
171
- }
172
-
173
- embeddedResources[name] = entry;
174
675
  }
175
676
 
176
- var mainCagContent = "";
177
- var mainCagPath = path.join(this.projectRoot, "main.cag");
178
- if (fs.existsSync(mainCagPath)) {
179
- mainCagContent = fs.readFileSync(mainCagPath, "utf-8");
180
- }
677
+ var blocks = [];
181
678
 
182
- var infoCagContent = "";
183
- var infoCagPath = path.join(this.projectRoot, "info.cag");
184
- if (fs.existsSync(infoCagPath)) {
185
- infoCagContent = fs.readFileSync(infoCagPath, "utf-8");
186
- }
187
-
188
- var entrySource = "";
189
- entrySource += "var PROJECT_INFO = " + JSON.stringify(this.info) + ";\n";
190
- entrySource += "var PROJECT_DEPENDENCIES = " + JSON.stringify(dependencies) + ";\n";
191
- entrySource += "var EMBEDDED_CODE = " + JSON.stringify(embeddedCode) + ";\n";
192
- entrySource += "var EMBEDDED_RESOURCES = " + JSON.stringify(embeddedResources) + ";\n";
193
- entrySource += "var MAIN_CAG = " + JSON.stringify(mainCagContent) + ";\n";
194
- entrySource += "var INFO_CAG = " + JSON.stringify(infoCagContent) + ";\n";
195
- entrySource += "\n";
196
- entrySource += this.getRuntimeSource();
679
+ var noise = function (x, z, s, scale) {
680
+ var nx = x / scale;
681
+ var nz = z / scale;
682
+ var a = Math.sin(nx * 12.9898 + nz * 78.233 + s) * 43758.5453;
683
+ return a - Math.floor(a);
684
+ };
197
685
 
198
- var entryPath = path.join(this.tempDir, "entry.js");
199
- fs.writeFileSync(entryPath, entrySource);
686
+ var smoothHeight = function (x, z) {
687
+ var h1 = noise(x, z, seed, 8.0) * 4;
688
+ var h2 = noise(x, z, seed + 100, 16.0) * 6;
689
+ var h3 = noise(x, z, seed + 200, 4.0) * 2;
690
+ var h4 = noise(x + 0.5, z + 0.5, seed + 300, 12.0) * 3;
691
+
692
+ var avg = 0;
693
+ var count = 0;
694
+ for (var dx = -1; dx <= 1; dx++) {
695
+ for (var dz = -1; dz <= 1; dz++) {
696
+ var n1 = noise(x + dx, z + dz, seed, 8.0) * 4;
697
+ var n2 = noise(x + dx, z + dz, seed + 100, 16.0) * 6;
698
+ avg += n1 + n2;
699
+ count++;
700
+ }
701
+ }
702
+ avg = avg / count;
200
703
 
201
- return entryPath;
202
- };
704
+ var raw = (h1 + h2 + h3 + h4) * 0.4 + avg * 0.6;
705
+ return Math.max(1, Math.min(Math.floor(raw), 12));
706
+ };
203
707
 
204
- ExeBuilder.prototype.generatePackageJson = function () {
205
- var pkg = {
206
- name: this.projectName,
207
- version: this.info.version || "1.0.0",
208
- main: "entry.js",
209
- bin: "entry.js",
210
- pkg: {
211
- assets: [],
212
- targets: ["node18"],
213
- outputPath: this.outputDir
708
+ for (var x = 0; x < size; x++) {
709
+ for (var z = 0; z < size; z++) {
710
+ var height = smoothHeight(x, z);
711
+ for (var y = 0; y <= height; y++) {
712
+ var blockType;
713
+ if (y === height) {
714
+ blockType = topLayer;
715
+ } else if (y === 0) {
716
+ blockType = bottomLayer;
717
+ } else if (y >= height - 1) {
718
+ blockType = topLayer === "grass" ? fillLayer : topLayer;
719
+ } else {
720
+ blockType = fillLayer;
721
+ }
722
+ blocks.push({ x: x, y: y, z: z, t: blockType });
723
+ }
724
+ if (hasWater && height < waterLevel) {
725
+ for (var wy = height + 1; wy <= waterLevel; wy++) {
726
+ blocks.push({ x: x, y: wy, z: z, t: "water" });
727
+ }
728
+ }
214
729
  }
215
- };
730
+ }
216
731
 
217
- var pkgPath = path.join(this.tempDir, "package.json");
218
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
219
- return pkgPath;
732
+ return blocks;
220
733
  };
221
734
 
222
- ExeBuilder.prototype.getRuntimeSource = function () {
223
- var src = "";
224
-
225
- src += "function CagRuntime() {\n";
226
- src += " this.info = PROJECT_INFO;\n";
227
- src += " this.dependencies = PROJECT_DEPENDENCIES;\n";
228
- src += " this.code = EMBEDDED_CODE;\n";
229
- src += " this.resources = EMBEDDED_RESOURCES;\n";
230
- src += " this.loadedModels = {};\n";
231
- src += " this.worlds = {};\n";
232
- src += " this.activeWorld = null;\n";
233
- src += " this.outputs = [];\n";
234
- src += "}\n\n";
235
-
236
- src += "CagRuntime.prototype.run = function () {\n";
237
- src += " this.print('========================================');\n";
238
- src += " this.print(' ' + this.info.ID);\n";
239
- src += " this.print(' Version: ' + this.info.version);\n";
240
- src += " this.print('========================================');\n";
241
- src += " this.print('');\n";
242
- src += " this.print('Dependencies: ' + this.dependencies.join(', '));\n";
243
- src += " this.print('Code files: ' + Object.keys(this.code).length);\n";
244
- src += " this.print('Resources: ' + Object.keys(this.resources).length);\n";
245
- src += " this.print('');\n";
246
- src += " var fileNames = Object.keys(this.code);\n";
247
- src += " for (var i = 0; i < fileNames.length; i++) {\n";
248
- src += " this.executeFile(fileNames[i], this.code[fileNames[i]]);\n";
249
- src += " }\n";
250
- src += " this.print('');\n";
251
- src += " this.print('Execution complete.');\n";
252
- src += " this.print('');\n";
253
- src += " this.print('Press Enter to exit...');\n";
254
- src += " this.waitForExit();\n";
255
- src += "};\n\n";
256
-
257
- src += "CagRuntime.prototype.executeFile = function (fileName, content) {\n";
258
- src += " this.print('Executing: ' + fileName);\n";
259
- src += " var lines = content.split('\\n');\n";
260
- src += " var imports = [];\n";
261
- src += " for (var i = 0; i < lines.length; i++) {\n";
262
- src += " var line = lines[i].trim();\n";
263
- src += " if (line === '') continue;\n";
264
- src += " if (line.startsWith('Import ')) {\n";
265
- src += " var impName = line.substring(7).trim();\n";
266
- src += " imports.push(impName);\n";
267
- src += " this.print(' Loaded: ' + impName);\n";
268
- src += " continue;\n";
269
- src += " }\n";
270
- src += " if (line.startsWith('{')) {\n";
271
- src += " this.executeFunction(line, imports);\n";
272
- src += " }\n";
273
- src += " }\n";
274
- src += "};\n\n";
275
-
276
- src += "CagRuntime.prototype.executeFunction = function (line, imports) {\n";
277
- src += " var inner = line.substring(1).trim();\n";
278
- src += " var parts = inner.split(/\\s+/);\n";
279
- src += " if (parts[0] !== 'function' || parts[1] !== 'use') return;\n";
280
- src += " var apiParts = [];\n";
281
- src += " var idx = 2;\n";
282
- src += " var apiName = parts[idx];\n";
283
- src += " if (idx + 2 < parts.length && parts[idx + 1] === undefined) idx++;\n";
284
- src += " var combined = parts.slice(2).join(' ');\n";
285
- src += " var apis = ['Model.API', 'WorldGen.API', 'Pull.API'];\n";
286
- src += " var foundApi = null;\n";
287
- src += " for (var a = 0; a < apis.length; a++) {\n";
288
- src += " if (combined.indexOf(apis[a]) === 0) {\n";
289
- src += " foundApi = apis[a];\n";
290
- src += " break;\n";
291
- src += " }\n";
292
- src += " }\n";
293
- src += " if (!foundApi) {\n";
294
- src += " this.print(' ERROR: Unknown API in: ' + line);\n";
295
- src += " return;\n";
296
- src += " }\n";
297
- src += " var afterApi = combined.substring(foundApi.length).trim();\n";
298
- src += " var actionParts = afterApi.split(/\\s+/);\n";
299
- src += " var action = actionParts[0] || '';\n";
300
- src += " var params = actionParts.slice(1);\n";
301
- src += " if (foundApi === 'Model.API') this.execModelAPI(action, params);\n";
302
- src += " else if (foundApi === 'WorldGen.API') this.execWorldGenAPI(action, params);\n";
303
- src += " else if (foundApi === 'Pull.API') this.execPullAPI(action, params);\n";
304
- src += "};\n\n";
305
-
306
- src += "CagRuntime.prototype.execModelAPI = function (action, params) {\n";
307
- src += " if (action === 'UseModel' || action === '1') {\n";
308
- src += " var modelName = params[0] || 'unknown';\n";
309
- src += " if (this.resources[modelName]) {\n";
310
- src += " this.loadedModels[modelName] = this.resources[modelName];\n";
311
- src += " this.print(' > Model loaded: ' + modelName + ' [paired: ' + this.resources[modelName].paired + ']');\n";
312
- src += " } else {\n";
313
- src += " this.loadedModels[modelName] = { name: modelName, paired: false };\n";
314
- src += " this.print(' > Model loaded (default): ' + modelName);\n";
315
- src += " }\n";
316
- src += " } else if (action === 'RemoveModel' || action === '2') {\n";
317
- src += " var rName = params[0] || 'unknown';\n";
318
- src += " delete this.loadedModels[rName];\n";
319
- src += " this.print(' > Model removed: ' + rName);\n";
320
- src += " } else if (action === 'ListModels' || action === '3') {\n";
321
- src += " var names = Object.keys(this.loadedModels);\n";
322
- src += " this.print(' > Loaded models: ' + (names.length > 0 ? names.join(', ') : 'none'));\n";
323
- src += " } else {\n";
324
- src += " this.print(' > Model.API.' + action + '(' + params.join(', ') + ')');\n";
325
- src += " }\n";
326
- src += "};\n\n";
327
-
328
- src += "CagRuntime.prototype.execWorldGenAPI = function (action, params) {\n";
329
- src += " if (action === 'generate' || action === '1') {\n";
330
- src += " var topLayer = null;\n";
331
- src += " for (var i = 0; i < params.length; i++) {\n";
332
- src += " if (params[i] === '=' && i + 1 < params.length) {\n";
333
- src += " topLayer = params[i + 1];\n";
334
- src += " }\n";
335
- src += " if (params[i] === 'top' && i + 3 < params.length && params[i + 1] === 'layer') {\n";
336
- src += " topLayer = params[i + 3] || params[i + 2];\n";
337
- src += " }\n";
338
- src += " }\n";
339
- src += " var worldId = 'world_' + Date.now();\n";
340
- src += " this.worlds[worldId] = { id: worldId, topLayer: topLayer, generated: true };\n";
341
- src += " this.activeWorld = worldId;\n";
342
- src += " this.print(' > World generated: ' + worldId + (topLayer ? ' (top: ' + topLayer + ')' : ''));\n";
343
- src += " } else if (action === 'destroy' || action === '2') {\n";
344
- src += " this.print(' > World destroyed');\n";
345
- src += " } else if (action === 'modify' || action === '3') {\n";
346
- src += " this.print(' > World modified: ' + params.join(' '));\n";
347
- src += " } else {\n";
348
- src += " this.print(' > WorldGen.API.' + action + '(' + params.join(', ') + ')');\n";
349
- src += " }\n";
350
- src += "};\n\n";
351
-
352
- src += "CagRuntime.prototype.execPullAPI = function (action, params) {\n";
353
- src += " if (action === 'retrieve' || action === '1') {\n";
354
- src += " var modelId = params[0] || 'unknown';\n";
355
- src += " this.print(' > Retrieved model: ' + modelId);\n";
356
- src += " } else if (action === 'search' || action === '2') {\n";
357
- src += " this.print(' > Search results for: ' + (params[0] || ''));\n";
358
- src += " } else if (action === 'list' || action === '3') {\n";
359
- src += " this.print(' > Listing available models');\n";
360
- src += " } else {\n";
361
- src += " this.print(' > Pull.API.' + action + '(' + params.join(', ') + ')');\n";
362
- src += " }\n";
363
- src += "};\n\n";
364
-
365
- src += "CagRuntime.prototype.print = function (text) {\n";
366
- src += " process.stdout.write(text + '\\n');\n";
367
- src += " this.outputs.push(text);\n";
368
- src += "};\n\n";
369
-
370
- src += "CagRuntime.prototype.waitForExit = function () {\n";
371
- src += " if (process.stdin.isTTY) {\n";
372
- src += " process.stdin.setRawMode(true);\n";
373
- src += " process.stdin.resume();\n";
374
- src += " process.stdin.once('data', function () {\n";
375
- src += " process.exit(0);\n";
376
- src += " });\n";
377
- src += " } else {\n";
378
- src += " setTimeout(function () { process.exit(0); }, 100);\n";
379
- src += " }\n";
380
- src += "};\n\n";
381
-
382
- src += "var runtime = new CagRuntime();\n";
383
- src += "runtime.run();\n";
384
-
385
- return src;
735
+ ExeBuilder.prototype.runPackager = function (platform, arch) {
736
+ var bin = this.findPackagerBin();
737
+ var cmd = bin + " \"" + this.tempDir + "\" " + this.projectName +
738
+ " --platform=" + platform +
739
+ " --arch=" + arch +
740
+ " --out=\"" + this.outputDir + "\"" +
741
+ " --overwrite" +
742
+ " --no-prune";
743
+
744
+ childProcess.execSync(cmd, {
745
+ cwd: this.tempDir,
746
+ stdio: "inherit",
747
+ shell: true
748
+ });
386
749
  };
387
750
 
388
- ExeBuilder.prototype.runPkg = function (entryFile, outputPath, target) {
389
- var pkgBin = this.findPkgBin();
390
- var cmd;
391
-
392
- if (pkgBin === "npx pkg") {
393
- cmd = 'npx pkg "' + entryFile + '" --target ' + target + ' --output "' + outputPath + '"';
394
- } else {
395
- cmd = '"' + pkgBin + '" "' + entryFile + '" --target ' + target + ' --output "' + outputPath + '"';
396
- }
397
-
398
- try {
399
- childProcess.execSync(cmd, {
400
- cwd: this.tempDir,
401
- stdio: "inherit",
402
- shell: true
403
- });
404
- } catch (e) {
405
- throw new Error("pkg build failed for target " + target + ": " + e.message);
406
- }
751
+ ExeBuilder.prototype.findPackagerBin = function () {
752
+ var cagRoot = path.join(__dirname, "..", "..");
407
753
 
408
- if (!fs.existsSync(outputPath)) {
409
- throw new Error("Build completed but output file not found: " + outputPath);
410
- }
411
- };
754
+ var localBin = path.join(cagRoot, "node_modules", ".bin", "electron-packager");
755
+ if (fs.existsSync(localBin)) return "\"" + localBin + "\"";
756
+ var localCmd = localBin + ".cmd";
757
+ if (fs.existsSync(localCmd)) return "\"" + localCmd + "\"";
412
758
 
413
- ExeBuilder.prototype.findPkgBin = function () {
414
- var projectLocal = path.join(this.projectRoot, "node_modules", ".bin", "pkg");
415
- if (fs.existsSync(projectLocal)) return projectLocal;
416
- var projectLocalCmd = projectLocal + ".cmd";
417
- if (fs.existsSync(projectLocalCmd)) return projectLocalCmd;
759
+ var projBin = path.join(this.projectRoot, "node_modules", ".bin", "electron-packager");
760
+ if (fs.existsSync(projBin)) return "\"" + projBin + "\"";
761
+ var projCmd = projBin + ".cmd";
762
+ if (fs.existsSync(projCmd)) return "\"" + projCmd + "\"";
418
763
 
419
- var cagRoot = path.join(__dirname, "..", "..");
420
- var cagLocal = path.join(cagRoot, "node_modules", ".bin", "pkg");
421
- if (fs.existsSync(cagLocal)) return cagLocal;
422
- var cagLocalCmd = cagLocal + ".cmd";
423
- if (fs.existsSync(cagLocalCmd)) return cagLocalCmd;
764
+ try {
765
+ childProcess.execSync("electron-packager --version", { stdio: "pipe" });
766
+ return "electron-packager";
767
+ } catch (e) {}
424
768
 
425
- var npmGlobalPrefix = "";
769
+ var npmPrefix = "";
426
770
  try {
427
- npmGlobalPrefix = childProcess.execSync("npm config get prefix", {
428
- stdio: "pipe"
429
- }).toString().trim();
430
- } catch (e) {
431
- npmGlobalPrefix = "";
432
- }
771
+ npmPrefix = childProcess.execSync("npm config get prefix", { stdio: "pipe" }).toString().trim();
772
+ } catch (e) {}
433
773
 
434
- if (npmGlobalPrefix) {
774
+ if (npmPrefix) {
435
775
  var isWin = process.platform === "win32";
436
- var globalBin;
437
776
  if (isWin) {
438
- globalBin = path.join(npmGlobalPrefix, "pkg.cmd");
439
- if (fs.existsSync(globalBin)) return globalBin;
440
- globalBin = path.join(npmGlobalPrefix, "node_modules", ".bin", "pkg.cmd");
441
- if (fs.existsSync(globalBin)) return globalBin;
777
+ var gCmd = path.join(npmPrefix, "electron-packager.cmd");
778
+ if (fs.existsSync(gCmd)) return "\"" + gCmd + "\"";
779
+ var gCmd2 = path.join(npmPrefix, "node_modules", ".bin", "electron-packager.cmd");
780
+ if (fs.existsSync(gCmd2)) return "\"" + gCmd2 + "\"";
442
781
  } else {
443
- globalBin = path.join(npmGlobalPrefix, "bin", "pkg");
444
- if (fs.existsSync(globalBin)) return globalBin;
782
+ var gBin = path.join(npmPrefix, "bin", "electron-packager");
783
+ if (fs.existsSync(gBin)) return "\"" + gBin + "\"";
445
784
  }
446
785
  }
447
786
 
448
787
  try {
449
- var whereResult = childProcess.execSync(
450
- process.platform === "win32" ? "where pkg 2>nul" : "which pkg 2>/dev/null",
451
- { stdio: "pipe" }
452
- ).toString().trim().split("\n")[0].trim();
453
- if (whereResult && fs.existsSync(whereResult)) return whereResult;
788
+ var whereCmd = process.platform === "win32" ? "where electron-packager 2>nul" : "which electron-packager 2>/dev/null";
789
+ var found = childProcess.execSync(whereCmd, { stdio: "pipe" }).toString().trim().split("\n")[0].trim();
790
+ if (found && fs.existsSync(found)) return "\"" + found + "\"";
454
791
  } catch (e) {}
455
792
 
456
- return "npx pkg";
793
+ return "npx electron-packager";
794
+ };
795
+
796
+ ExeBuilder.prototype.mapPlatform = function (p) {
797
+ if (p === "win") return "win32";
798
+ if (p === "macos") return "darwin";
799
+ return "linux";
457
800
  };
458
801
 
459
802
  ExeBuilder.prototype.cleanup = function () {
@@ -462,9 +805,7 @@ ExeBuilder.prototype.cleanup = function () {
462
805
 
463
806
  ExeBuilder.prototype.removeDirectory = function (dir) {
464
807
  if (!fs.existsSync(dir)) return;
465
-
466
808
  var entries = fs.readdirSync(dir, { withFileTypes: true });
467
-
468
809
  for (var i = 0; i < entries.length; i++) {
469
810
  var fullPath = path.join(dir, entries[i].name);
470
811
  if (entries[i].isDirectory()) {
@@ -473,14 +814,27 @@ ExeBuilder.prototype.removeDirectory = function (dir) {
473
814
  fs.unlinkSync(fullPath);
474
815
  }
475
816
  }
476
-
477
817
  fs.rmdirSync(dir);
478
818
  };
479
819
 
480
820
  ExeBuilder.prototype.getFileSize = function (filePath) {
481
821
  if (!fs.existsSync(filePath)) return 0;
482
- var stats = fs.statSync(filePath);
483
- return stats.size;
822
+ return fs.statSync(filePath).size;
823
+ };
824
+
825
+ ExeBuilder.prototype.getDirectorySize = function (dir) {
826
+ if (!fs.existsSync(dir)) return 0;
827
+ var total = 0;
828
+ var entries = fs.readdirSync(dir, { withFileTypes: true });
829
+ for (var i = 0; i < entries.length; i++) {
830
+ var fullPath = path.join(dir, entries[i].name);
831
+ if (entries[i].isDirectory()) {
832
+ total += this.getDirectorySize(fullPath);
833
+ } else {
834
+ total += fs.statSync(fullPath).size;
835
+ }
836
+ }
837
+ return total;
484
838
  };
485
839
 
486
840
  ExeBuilder.prototype.formatSize = function (bytes) {