@erik9994857/cag 1.0.2 → 2.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/defaults/main.cag +8 -3
- package/defaults/src/code/example.cagc +34 -0
- package/package.json +2 -4
- package/src/api/api-registry.js +20 -0
- package/src/api/camera-api.js +75 -0
- package/src/api/chunk-api.js +75 -0
- package/src/api/player-api.js +74 -0
- package/src/api/render-api.js +80 -0
- package/src/api/window-api.js +69 -0
- package/src/builder/exe-builder.js +929 -499
- package/src/cli/cag-cli.js +9 -2
- package/src/index.js +2 -2
- package/src/parser/cag-parser.js +56 -4
- package/src/parser/cagc-parser.js +14 -2
- package/src/parser/tokenizer.js +14 -2
- package/src/runtime/electron-runner.js +644 -0
- package/src/runtime/executor.js +7 -0
|
@@ -1,499 +1,929 @@
|
|
|
1
|
-
var path = require("path");
|
|
2
|
-
var fs = require("fs");
|
|
3
|
-
var childProcess = require("child_process");
|
|
4
|
-
|
|
5
|
-
function ExeBuilder(engine) {
|
|
6
|
-
this.engine = engine;
|
|
7
|
-
this.info = engine.getInfo();
|
|
8
|
-
this.projectRoot = engine.projectRoot;
|
|
9
|
-
this.outputDir = path.join(this.projectRoot, "dist");
|
|
10
|
-
this.tempDir = path.join(this.outputDir, ".build
|
|
11
|
-
this.projectName = this.info.ID.split(".")[1] || this.info.ID.split(".")[0] || "cag-app";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
ExeBuilder.prototype.build = function (options) {
|
|
15
|
-
options = options || {};
|
|
16
|
-
var platform = options.platform || this.detectPlatform();
|
|
17
|
-
var arch = options.arch || "x64";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{ platform: "
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
var
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
if (
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
};
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
if (
|
|
422
|
-
|
|
423
|
-
if (
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
var
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
var
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
1
|
+
var path = require("path");
|
|
2
|
+
var fs = require("fs");
|
|
3
|
+
var childProcess = require("child_process");
|
|
4
|
+
|
|
5
|
+
function ExeBuilder(engine) {
|
|
6
|
+
this.engine = engine;
|
|
7
|
+
this.info = engine.getInfo();
|
|
8
|
+
this.projectRoot = engine.projectRoot;
|
|
9
|
+
this.outputDir = path.join(this.projectRoot, "dist");
|
|
10
|
+
this.tempDir = path.join(this.outputDir, ".cag-build");
|
|
11
|
+
this.projectName = this.info.ID.split(".")[1] || this.info.ID.split(".")[0] || "cag-app";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
ExeBuilder.prototype.build = function (options) {
|
|
15
|
+
options = options || {};
|
|
16
|
+
var platform = options.platform || this.detectPlatform();
|
|
17
|
+
var arch = options.arch || "x64";
|
|
18
|
+
|
|
19
|
+
this.ensureDirectories();
|
|
20
|
+
var html = this.getRendererSource();
|
|
21
|
+
var exeName, exePath;
|
|
22
|
+
|
|
23
|
+
if (platform === "win") {
|
|
24
|
+
var iconPath = path.join(this.tempDir, "icon.ico");
|
|
25
|
+
this.generateIcon(iconPath);
|
|
26
|
+
var csSource = this.generateCSharpSource(html);
|
|
27
|
+
var csPath = path.join(this.tempDir, "CaGLauncher.cs");
|
|
28
|
+
fs.writeFileSync(csPath, csSource);
|
|
29
|
+
exeName = this.projectName + ".exe";
|
|
30
|
+
exePath = path.join(this.outputDir, exeName);
|
|
31
|
+
this.compileCSharp(csPath, exePath, iconPath);
|
|
32
|
+
} else if (platform === "macos") {
|
|
33
|
+
exeName = this.projectName + ".app";
|
|
34
|
+
exePath = path.join(this.outputDir, exeName);
|
|
35
|
+
this.generateMacApp(html, exePath);
|
|
36
|
+
} else {
|
|
37
|
+
exeName = this.projectName;
|
|
38
|
+
exePath = path.join(this.outputDir, exeName);
|
|
39
|
+
this.generateLinuxApp(html, exePath);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.cleanup();
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
outputPath: exePath,
|
|
46
|
+
outputDir: this.outputDir,
|
|
47
|
+
outputName: exeName,
|
|
48
|
+
platform: platform,
|
|
49
|
+
arch: arch,
|
|
50
|
+
size: this.getFileSize(exePath) || this.getDirectorySize(exePath),
|
|
51
|
+
success: true
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
ExeBuilder.prototype.buildAll = function () {
|
|
56
|
+
var results = [];
|
|
57
|
+
var targets = [
|
|
58
|
+
{ platform: "win", arch: "x64", ext: ".exe" },
|
|
59
|
+
{ platform: "macos", arch: "x64", ext: ".app" },
|
|
60
|
+
{ platform: "linux", arch: "x64", ext: "" }
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
this.ensureDirectories();
|
|
64
|
+
var html = this.getRendererSource();
|
|
65
|
+
|
|
66
|
+
for (var i = 0; i < targets.length; i++) {
|
|
67
|
+
var t = targets[i];
|
|
68
|
+
try {
|
|
69
|
+
var exeName, exePath;
|
|
70
|
+
if (t.platform === "win") {
|
|
71
|
+
var iconPath = path.join(this.tempDir, "icon.ico");
|
|
72
|
+
this.generateIcon(iconPath);
|
|
73
|
+
var csSource = this.generateCSharpSource(html);
|
|
74
|
+
var csPath = path.join(this.tempDir, "CaGLauncher.cs");
|
|
75
|
+
fs.writeFileSync(csPath, csSource);
|
|
76
|
+
exeName = this.projectName + "-win-" + t.arch + t.ext;
|
|
77
|
+
exePath = path.join(this.outputDir, exeName);
|
|
78
|
+
this.compileCSharp(csPath, exePath, iconPath);
|
|
79
|
+
} else if (t.platform === "macos") {
|
|
80
|
+
exeName = this.projectName + "-macos-" + t.arch + t.ext;
|
|
81
|
+
exePath = path.join(this.outputDir, exeName);
|
|
82
|
+
this.generateMacApp(html, exePath);
|
|
83
|
+
} else {
|
|
84
|
+
exeName = this.projectName + "-linux-" + t.arch;
|
|
85
|
+
exePath = path.join(this.outputDir, exeName);
|
|
86
|
+
this.generateLinuxApp(html, exePath);
|
|
87
|
+
}
|
|
88
|
+
results.push({
|
|
89
|
+
outputPath: exePath,
|
|
90
|
+
outputDir: this.outputDir,
|
|
91
|
+
outputName: exeName,
|
|
92
|
+
platform: t.platform,
|
|
93
|
+
arch: t.arch,
|
|
94
|
+
size: this.getFileSize(exePath) || this.getDirectorySize(exePath),
|
|
95
|
+
success: true
|
|
96
|
+
});
|
|
97
|
+
} catch (e) {
|
|
98
|
+
results.push({
|
|
99
|
+
outputName: this.projectName + t.ext,
|
|
100
|
+
platform: t.platform,
|
|
101
|
+
arch: t.arch,
|
|
102
|
+
success: false,
|
|
103
|
+
error: e.message
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.cleanup();
|
|
109
|
+
return results;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
ExeBuilder.prototype.ensureDirectories = function () {
|
|
113
|
+
if (!fs.existsSync(this.outputDir)) fs.mkdirSync(this.outputDir, { recursive: true });
|
|
114
|
+
if (fs.existsSync(this.tempDir)) this.removeDirectory(this.tempDir);
|
|
115
|
+
fs.mkdirSync(this.tempDir, { recursive: true });
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
ExeBuilder.prototype.generateIcon = function (outputPath) {
|
|
119
|
+
var width = 32;
|
|
120
|
+
var height = 32;
|
|
121
|
+
var header = Buffer.alloc(6);
|
|
122
|
+
header.writeUInt16LE(0, 0);
|
|
123
|
+
header.writeUInt16LE(1, 2);
|
|
124
|
+
header.writeUInt16LE(1, 4);
|
|
125
|
+
var bmpHeader = Buffer.alloc(40);
|
|
126
|
+
bmpHeader.writeUInt32LE(40, 0);
|
|
127
|
+
bmpHeader.writeInt32LE(width, 4);
|
|
128
|
+
bmpHeader.writeInt32LE(height * 2, 8);
|
|
129
|
+
bmpHeader.writeUInt16LE(1, 12);
|
|
130
|
+
bmpHeader.writeUInt16LE(32, 14);
|
|
131
|
+
bmpHeader.writeUInt32LE(0, 16);
|
|
132
|
+
bmpHeader.writeUInt32LE(width * height * 4, 20);
|
|
133
|
+
var pixelData = Buffer.alloc(width * height * 4);
|
|
134
|
+
for (var i = 0; i < width * height; i++) {
|
|
135
|
+
pixelData.writeUInt8(0xFF, i * 4);
|
|
136
|
+
pixelData.writeUInt8(0xFF, i * 4 + 1);
|
|
137
|
+
pixelData.writeUInt8(0xFF, i * 4 + 2);
|
|
138
|
+
pixelData.writeUInt8(0xFF, i * 4 + 3);
|
|
139
|
+
}
|
|
140
|
+
var andMask = Buffer.alloc(width * height / 8, 0x00);
|
|
141
|
+
var imageDataSize = bmpHeader.length + pixelData.length + andMask.length;
|
|
142
|
+
var dirEntry = Buffer.alloc(16);
|
|
143
|
+
dirEntry.writeUInt8(width, 0);
|
|
144
|
+
dirEntry.writeUInt8(height, 1);
|
|
145
|
+
dirEntry.writeUInt8(0, 2);
|
|
146
|
+
dirEntry.writeUInt8(0, 3);
|
|
147
|
+
dirEntry.writeUInt16LE(1, 4);
|
|
148
|
+
dirEntry.writeUInt16LE(32, 6);
|
|
149
|
+
dirEntry.writeUInt32LE(imageDataSize, 8);
|
|
150
|
+
dirEntry.writeUInt32LE(6 + 16, 12);
|
|
151
|
+
var ico = Buffer.concat([header, dirEntry, bmpHeader, pixelData, andMask]);
|
|
152
|
+
fs.writeFileSync(outputPath, ico);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
ExeBuilder.prototype.generateCSharpSource = function (html) {
|
|
156
|
+
var b64 = Buffer.from(html, 'utf-8').toString('base64');
|
|
157
|
+
var cs = [
|
|
158
|
+
'using System;',
|
|
159
|
+
'using System.IO;',
|
|
160
|
+
'using System.Diagnostics;',
|
|
161
|
+
'using System.Text;',
|
|
162
|
+
'',
|
|
163
|
+
'class CaGLauncher {',
|
|
164
|
+
' static string DATA = "' + b64 + '";',
|
|
165
|
+
'',
|
|
166
|
+
' [STAThread]',
|
|
167
|
+
' static void Main() {',
|
|
168
|
+
' string html = Encoding.UTF8.GetString(Convert.FromBase64String(DATA));',
|
|
169
|
+
' string tempDir = Path.Combine(Path.GetTempPath(), "cag_" + Guid.NewGuid().ToString("N"));',
|
|
170
|
+
' Directory.CreateDirectory(tempDir);',
|
|
171
|
+
' string htmlPath = Path.Combine(tempDir, "game.html");',
|
|
172
|
+
' File.WriteAllText(htmlPath, html, Encoding.UTF8);',
|
|
173
|
+
' string profileDir = Path.Combine(tempDir, "profile");',
|
|
174
|
+
' Directory.CreateDirectory(profileDir);',
|
|
175
|
+
' string browser = FindBrowser();',
|
|
176
|
+
' if (browser != null) {',
|
|
177
|
+
' string fileUrl = "file:///" + htmlPath.Replace("\\\\", "/");',
|
|
178
|
+
' string profUrl = profileDir.Replace("\\\\", "/");',
|
|
179
|
+
' ProcessStartInfo psi = new ProcessStartInfo();',
|
|
180
|
+
' psi.FileName = browser;',
|
|
181
|
+
' psi.Arguments = "--app=\\"" + fileUrl + "\\" --window-size=1280,720 --user-data-dir=\\"" + profUrl + "\\" --no-first-run --disable-extensions --disable-default-apps";',
|
|
182
|
+
' psi.UseShellExecute = false;',
|
|
183
|
+
' Process p = Process.Start(psi);',
|
|
184
|
+
' p.WaitForExit();',
|
|
185
|
+
' } else {',
|
|
186
|
+
' Process.Start(new ProcessStartInfo(htmlPath) { UseShellExecute = true });',
|
|
187
|
+
' System.Threading.Thread.Sleep(3000);',
|
|
188
|
+
' }',
|
|
189
|
+
' try { Directory.Delete(tempDir, true); } catch {}',
|
|
190
|
+
' }',
|
|
191
|
+
'',
|
|
192
|
+
' static string FindBrowser() {',
|
|
193
|
+
' string[] paths = new string[] {',
|
|
194
|
+
' Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft", "Edge", "Application", "msedge.exe"),',
|
|
195
|
+
' Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft", "Edge", "Application", "msedge.exe"),',
|
|
196
|
+
' Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Google", "Chrome", "Application", "chrome.exe"),',
|
|
197
|
+
' Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Google", "Chrome", "Application", "chrome.exe"),',
|
|
198
|
+
' Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Google", "Chrome", "Application", "chrome.exe")',
|
|
199
|
+
' };',
|
|
200
|
+
' foreach (string p in paths) {',
|
|
201
|
+
' if (File.Exists(p)) return p;',
|
|
202
|
+
' }',
|
|
203
|
+
' return null;',
|
|
204
|
+
' }',
|
|
205
|
+
'}'
|
|
206
|
+
].join('\n');
|
|
207
|
+
return cs;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
ExeBuilder.prototype.findCscCompiler = function () {
|
|
211
|
+
var frameworkPaths = [
|
|
212
|
+
'C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe',
|
|
213
|
+
'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe'
|
|
214
|
+
];
|
|
215
|
+
for (var i = 0; i < frameworkPaths.length; i++) {
|
|
216
|
+
if (fs.existsSync(frameworkPaths[i])) return frameworkPaths[i];
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
childProcess.execSync('csc /help', { stdio: 'pipe', timeout: 5000 });
|
|
220
|
+
return 'csc';
|
|
221
|
+
} catch (e) {}
|
|
222
|
+
return null;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
ExeBuilder.prototype.compileCSharp = function (csPath, outputPath, iconPath) {
|
|
226
|
+
var csc = this.findCscCompiler();
|
|
227
|
+
if (!csc) {
|
|
228
|
+
throw new Error('C# compiler (csc.exe) not found. Ensure .NET Framework is installed.');
|
|
229
|
+
}
|
|
230
|
+
var cmd = '"' + csc + '" /target:winexe /out:"' + outputPath + '"';
|
|
231
|
+
if (iconPath && fs.existsSync(iconPath)) {
|
|
232
|
+
cmd += ' /win32icon:"' + iconPath + '"';
|
|
233
|
+
}
|
|
234
|
+
cmd += ' /optimize "' + csPath + '"';
|
|
235
|
+
childProcess.execSync(cmd, {
|
|
236
|
+
cwd: this.tempDir,
|
|
237
|
+
stdio: 'inherit',
|
|
238
|
+
shell: true
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
ExeBuilder.prototype.getRendererSource = function () {
|
|
243
|
+
var blocks = this.generateWorldBlocks();
|
|
244
|
+
var info = this.info;
|
|
245
|
+
|
|
246
|
+
var css = [
|
|
247
|
+
"* { margin: 0; padding: 0; box-sizing: border-box; }",
|
|
248
|
+
"body { background: #1a1a2e; overflow: hidden; font-family: monospace; }",
|
|
249
|
+
"#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; }",
|
|
250
|
+
"#loading.fade-out { opacity: 0; pointer-events: none; }",
|
|
251
|
+
"#loading h1 { font-size: 64px; color: #4ecca3; margin-bottom: 4px; letter-spacing: 6px; text-shadow: 0 0 30px rgba(78,204,163,0.3); }",
|
|
252
|
+
"#loading h2 { font-size: 14px; color: #666; margin-bottom: 30px; font-weight: normal; letter-spacing: 2px; }",
|
|
253
|
+
"#load-status { font-size: 12px; color: #555; margin-bottom: 12px; min-height: 18px; transition: color 0.3s; }",
|
|
254
|
+
"#bar-outer { width: 300px; height: 3px; background: #2a2a3e; border-radius: 2px; overflow: hidden; }",
|
|
255
|
+
"#bar-inner { width: 0%; height: 100%; background: linear-gradient(90deg, #4ecca3, #45b7d1); border-radius: 2px; transition: width 0.4s ease-out; }",
|
|
256
|
+
"#loading .version-tag { font-size: 11px; color: #444; margin-top: 20px; }",
|
|
257
|
+
"#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; }",
|
|
258
|
+
"#click-overlay:hover { background: rgba(0,0,0,0.55); }",
|
|
259
|
+
"#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; }",
|
|
260
|
+
"#click-overlay:hover .play-icon { transform: scale(1.1); border-color: #45b7d1; }",
|
|
261
|
+
"#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; }",
|
|
262
|
+
"#click-overlay span { color: #888; font-size: 16px; letter-spacing: 3px; }",
|
|
263
|
+
"canvas { display: block; position: fixed; top: 0; left: 0; }",
|
|
264
|
+
"#hud { position: fixed; top: 10px; left: 10px; z-index: 100; pointer-events: none; }",
|
|
265
|
+
"#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; }",
|
|
266
|
+
"#hud-box div { color: #bbb; font-size: 11px; line-height: 17px; }",
|
|
267
|
+
"#hud-box .hud-title { color: #4ecca3; font-size: 13px; font-weight: bold; margin-bottom: 3px; letter-spacing: 1px; }",
|
|
268
|
+
"#hud-box .hud-sep { border-top: 1px solid #333; margin: 4px 0; }",
|
|
269
|
+
"#crosshair { position: fixed; top: 50%; left: 50%; width: 24px; height: 24px; margin: -12px 0 0 -12px; z-index: 100; pointer-events: none; }",
|
|
270
|
+
"#crosshair::before { content: ''; position: absolute; top: 11px; left: 3px; width: 18px; height: 2px; background: rgba(255,255,255,0.6); border-radius: 1px; }",
|
|
271
|
+
"#crosshair::after { content: ''; position: absolute; top: 3px; left: 11px; width: 2px; height: 18px; background: rgba(255,255,255,0.6); border-radius: 1px; }",
|
|
272
|
+
"#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); }",
|
|
273
|
+
"#controls-hint b { color: #888; }"
|
|
274
|
+
].join("\n");
|
|
275
|
+
|
|
276
|
+
var vs = [
|
|
277
|
+
"attribute vec3 aPos;",
|
|
278
|
+
"attribute vec3 aColor;",
|
|
279
|
+
"attribute vec3 aNormal;",
|
|
280
|
+
"uniform mat4 uProj;",
|
|
281
|
+
"uniform mat4 uView;",
|
|
282
|
+
"varying vec3 vColor;",
|
|
283
|
+
"varying vec3 vNormal;",
|
|
284
|
+
"varying vec3 vWorldPos;",
|
|
285
|
+
"void main() {",
|
|
286
|
+
" vColor = aColor;",
|
|
287
|
+
" vNormal = aNormal;",
|
|
288
|
+
" vWorldPos = aPos;",
|
|
289
|
+
" gl_Position = uProj * uView * vec4(aPos, 1.0);",
|
|
290
|
+
"}"
|
|
291
|
+
].join("\\n");
|
|
292
|
+
|
|
293
|
+
var fs_shader = [
|
|
294
|
+
"precision mediump float;",
|
|
295
|
+
"varying vec3 vColor;",
|
|
296
|
+
"varying vec3 vNormal;",
|
|
297
|
+
"varying vec3 vWorldPos;",
|
|
298
|
+
"uniform vec3 uSunDir;",
|
|
299
|
+
"uniform vec3 uSunColor;",
|
|
300
|
+
"uniform vec3 uAmbient;",
|
|
301
|
+
"uniform vec3 uFogColor;",
|
|
302
|
+
"uniform float uFogNear;",
|
|
303
|
+
"uniform float uFogFar;",
|
|
304
|
+
"uniform vec3 uCamPos;",
|
|
305
|
+
"void main() {",
|
|
306
|
+
" vec3 norm = normalize(vNormal);",
|
|
307
|
+
" float diff = max(dot(norm, normalize(uSunDir)), 0.0);",
|
|
308
|
+
" vec3 lit = vColor * (uAmbient + uSunColor * diff);",
|
|
309
|
+
" float dist = length(vWorldPos - uCamPos);",
|
|
310
|
+
" float fog = clamp((dist - uFogNear) / (uFogFar - uFogNear), 0.0, 1.0);",
|
|
311
|
+
" vec3 final = mix(lit, uFogColor, fog);",
|
|
312
|
+
" gl_FragColor = vec4(final, 1.0);",
|
|
313
|
+
"}"
|
|
314
|
+
].join("\\n");
|
|
315
|
+
|
|
316
|
+
var js = [];
|
|
317
|
+
js.push("var BLOCKS = " + JSON.stringify(blocks) + ";");
|
|
318
|
+
js.push("var INFO = " + JSON.stringify(info) + ";");
|
|
319
|
+
js.push("");
|
|
320
|
+
js.push("var VS_SRC = \"" + vs + "\";");
|
|
321
|
+
js.push("var FS_SRC = \"" + fs_shader + "\";");
|
|
322
|
+
js.push("");
|
|
323
|
+
js.push("var cag = {");
|
|
324
|
+
js.push(" gl: null, canvas: null, program: null,");
|
|
325
|
+
js.push(" camX: 16, camY: 12, camZ: 16,");
|
|
326
|
+
js.push(" pitch: -0.5, yaw: 0.8,");
|
|
327
|
+
js.push(" keys: {}, locked: false,");
|
|
328
|
+
js.push(" velY: 0, onGround: false, gravity: 0.015,");
|
|
329
|
+
js.push(" fps: 0, frames: 0, lastFps: 0,");
|
|
330
|
+
js.push(" vbo: null, vertCount: 0,");
|
|
331
|
+
js.push(" blockMap: {},");
|
|
332
|
+
js.push(" uProj: null, uView: null, uSunDir: null, uSunColor: null,");
|
|
333
|
+
js.push(" uAmbient: null, uFogColor: null, uFogNear: null, uFogFar: null, uCamPos: null,");
|
|
334
|
+
js.push("");
|
|
335
|
+
js.push(" init: function () {");
|
|
336
|
+
js.push(" this.canvas = document.getElementById('cag-canvas');");
|
|
337
|
+
js.push(" this.gl = this.canvas.getContext('webgl', { antialias: true });");
|
|
338
|
+
js.push(" if (!this.gl) { alert('WebGL not supported'); return; }");
|
|
339
|
+
js.push(" this.resize();");
|
|
340
|
+
js.push(" this.buildBlockMap();");
|
|
341
|
+
js.push(" this.compileShaders();");
|
|
342
|
+
js.push(" this.buildMesh();");
|
|
343
|
+
js.push(" this.bindInput();");
|
|
344
|
+
js.push(" var loadEl = document.getElementById('loading');");
|
|
345
|
+
js.push(" loadEl.classList.add('fade-out');");
|
|
346
|
+
js.push(" setTimeout(function () {");
|
|
347
|
+
js.push(" loadEl.style.display = 'none';");
|
|
348
|
+
js.push(" document.getElementById('click-overlay').style.display = 'flex';");
|
|
349
|
+
js.push(" }, 500);");
|
|
350
|
+
js.push(" this.lastFps = performance.now();");
|
|
351
|
+
js.push(" this.loop();");
|
|
352
|
+
js.push(" },");
|
|
353
|
+
js.push("");
|
|
354
|
+
js.push(" buildBlockMap: function () {");
|
|
355
|
+
js.push(" for (var i = 0; i < BLOCKS.length; i++) {");
|
|
356
|
+
js.push(" var b = BLOCKS[i];");
|
|
357
|
+
js.push(" this.blockMap[b.x + ',' + b.y + ',' + b.z] = b;");
|
|
358
|
+
js.push(" }");
|
|
359
|
+
js.push(" },");
|
|
360
|
+
js.push("");
|
|
361
|
+
js.push(" hasBlock: function (x, y, z) {");
|
|
362
|
+
js.push(" return this.blockMap[x + ',' + y + ',' + z] !== undefined;");
|
|
363
|
+
js.push(" },");
|
|
364
|
+
js.push("");
|
|
365
|
+
js.push(" compileShaders: function () {");
|
|
366
|
+
js.push(" var gl = this.gl;");
|
|
367
|
+
js.push(" var vs = gl.createShader(gl.VERTEX_SHADER);");
|
|
368
|
+
js.push(" gl.shaderSource(vs, VS_SRC); gl.compileShader(vs);");
|
|
369
|
+
js.push(" var fs = gl.createShader(gl.FRAGMENT_SHADER);");
|
|
370
|
+
js.push(" gl.shaderSource(fs, FS_SRC); gl.compileShader(fs);");
|
|
371
|
+
js.push(" this.program = gl.createProgram();");
|
|
372
|
+
js.push(" gl.attachShader(this.program, vs);");
|
|
373
|
+
js.push(" gl.attachShader(this.program, fs);");
|
|
374
|
+
js.push(" gl.linkProgram(this.program);");
|
|
375
|
+
js.push(" gl.useProgram(this.program);");
|
|
376
|
+
js.push(" this.uProj = gl.getUniformLocation(this.program, 'uProj');");
|
|
377
|
+
js.push(" this.uView = gl.getUniformLocation(this.program, 'uView');");
|
|
378
|
+
js.push(" this.uSunDir = gl.getUniformLocation(this.program, 'uSunDir');");
|
|
379
|
+
js.push(" this.uSunColor = gl.getUniformLocation(this.program, 'uSunColor');");
|
|
380
|
+
js.push(" this.uAmbient = gl.getUniformLocation(this.program, 'uAmbient');");
|
|
381
|
+
js.push(" this.uFogColor = gl.getUniformLocation(this.program, 'uFogColor');");
|
|
382
|
+
js.push(" this.uFogNear = gl.getUniformLocation(this.program, 'uFogNear');");
|
|
383
|
+
js.push(" this.uFogFar = gl.getUniformLocation(this.program, 'uFogFar');");
|
|
384
|
+
js.push(" this.uCamPos = gl.getUniformLocation(this.program, 'uCamPos');");
|
|
385
|
+
js.push(" gl.uniform3f(this.uSunDir, 0.4, 0.8, 0.3);");
|
|
386
|
+
js.push(" gl.uniform3f(this.uSunColor, 1.0, 0.95, 0.85);");
|
|
387
|
+
js.push(" gl.uniform3f(this.uAmbient, 0.35, 0.38, 0.5);");
|
|
388
|
+
js.push(" gl.uniform3f(this.uFogColor, 0.53, 0.81, 0.92);");
|
|
389
|
+
js.push(" gl.uniform1f(this.uFogNear, 30.0);");
|
|
390
|
+
js.push(" gl.uniform1f(this.uFogFar, 70.0);");
|
|
391
|
+
js.push(" },");
|
|
392
|
+
js.push("");
|
|
393
|
+
js.push(" getBlockColor: function (b, face) {");
|
|
394
|
+
js.push(" var r, g, bl;");
|
|
395
|
+
js.push(" if (b.t === 'grass') {");
|
|
396
|
+
js.push(" if (face === 'top') { r = 0.34; g = 0.68; bl = 0.24; }");
|
|
397
|
+
js.push(" else if (face === 'bottom') { r = 0.55; g = 0.38; bl = 0.18; }");
|
|
398
|
+
js.push(" else { r = 0.42; g = 0.50; bl = 0.22; }");
|
|
399
|
+
js.push(" } else if (b.t === 'dirt') {");
|
|
400
|
+
js.push(" r = 0.55; g = 0.38; bl = 0.18;");
|
|
401
|
+
js.push(" } else if (b.t === 'stone') {");
|
|
402
|
+
js.push(" if (face === 'top') { r = 0.58; g = 0.58; bl = 0.58; }");
|
|
403
|
+
js.push(" else { r = 0.50; g = 0.50; bl = 0.50; }");
|
|
404
|
+
js.push(" } else if (b.t === 'sand') {");
|
|
405
|
+
js.push(" if (face === 'top') { r = 0.86; g = 0.82; bl = 0.58; }");
|
|
406
|
+
js.push(" else { r = 0.80; g = 0.76; bl = 0.52; }");
|
|
407
|
+
js.push(" } else if (b.t === 'water') {");
|
|
408
|
+
js.push(" if (face === 'top') { r = 0.15; g = 0.45; bl = 0.75; }");
|
|
409
|
+
js.push(" else { r = 0.10; g = 0.35; bl = 0.65; }");
|
|
410
|
+
js.push(" } else if (b.t === 'snow') {");
|
|
411
|
+
js.push(" if (face === 'top') { r = 0.95; g = 0.96; bl = 0.98; }");
|
|
412
|
+
js.push(" else { r = 0.88; g = 0.90; bl = 0.92; }");
|
|
413
|
+
js.push(" } else if (b.t === 'wood' || b.t === 'log') {");
|
|
414
|
+
js.push(" if (face === 'top' || face === 'bottom') { r = 0.62; g = 0.52; bl = 0.30; }");
|
|
415
|
+
js.push(" else { r = 0.45; g = 0.32; bl = 0.18; }");
|
|
416
|
+
js.push(" } else if (b.t === 'leaf' || b.t === 'leaves') {");
|
|
417
|
+
js.push(" r = 0.20; g = 0.55; bl = 0.15;");
|
|
418
|
+
js.push(" } else if (b.t === 'planks') {");
|
|
419
|
+
js.push(" r = 0.72; g = 0.58; bl = 0.35;");
|
|
420
|
+
js.push(" } else if (b.t === 'cobblestone' || b.t === 'cobble') {");
|
|
421
|
+
js.push(" if (face === 'top') { r = 0.52; g = 0.52; bl = 0.52; }");
|
|
422
|
+
js.push(" else { r = 0.44; g = 0.44; bl = 0.44; }");
|
|
423
|
+
js.push(" } else if (b.t === 'gravel') {");
|
|
424
|
+
js.push(" r = 0.56; g = 0.54; bl = 0.50;");
|
|
425
|
+
js.push(" } else if (b.t === 'clay') {");
|
|
426
|
+
js.push(" r = 0.62; g = 0.60; bl = 0.58;");
|
|
427
|
+
js.push(" } else if (b.t === 'iron' || b.t === 'ore') {");
|
|
428
|
+
js.push(" r = 0.65; g = 0.60; bl = 0.55;");
|
|
429
|
+
js.push(" } else if (b.t === 'gold') {");
|
|
430
|
+
js.push(" r = 0.90; g = 0.78; bl = 0.20;");
|
|
431
|
+
js.push(" } else if (b.t === 'diamond') {");
|
|
432
|
+
js.push(" r = 0.30; g = 0.85; bl = 0.88;");
|
|
433
|
+
js.push(" } else if (b.t === 'lava') {");
|
|
434
|
+
js.push(" r = 0.95; g = 0.35; bl = 0.05;");
|
|
435
|
+
js.push(" } else if (b.t === 'brick') {");
|
|
436
|
+
js.push(" r = 0.65; g = 0.32; bl = 0.25;");
|
|
437
|
+
js.push(" } else {");
|
|
438
|
+
js.push(" var hash = 0;");
|
|
439
|
+
js.push(" for (var ci = 0; ci < b.t.length; ci++) hash = ((hash << 5) - hash) + b.t.charCodeAt(ci);");
|
|
440
|
+
js.push(" r = 0.3 + (((hash & 0xFF) / 255) * 0.5);");
|
|
441
|
+
js.push(" g = 0.3 + ((((hash >> 8) & 0xFF) / 255) * 0.5);");
|
|
442
|
+
js.push(" bl = 0.3 + ((((hash >> 16) & 0xFF) / 255) * 0.5);");
|
|
443
|
+
js.push(" }");
|
|
444
|
+
js.push(" var v = 0.85 + (b.y / 12.0) * 0.15;");
|
|
445
|
+
js.push(" return [r * v, g * v, bl * v];");
|
|
446
|
+
js.push(" },");
|
|
447
|
+
js.push("");
|
|
448
|
+
js.push(" buildMesh: function () {");
|
|
449
|
+
js.push(" var verts = [];");
|
|
450
|
+
js.push(" var self = this;");
|
|
451
|
+
js.push(" function quad(x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, nx,ny,nz, c) {");
|
|
452
|
+
js.push(" verts.push(x1,y1,z1, c[0],c[1],c[2], nx,ny,nz);");
|
|
453
|
+
js.push(" verts.push(x2,y2,z2, c[0],c[1],c[2], nx,ny,nz);");
|
|
454
|
+
js.push(" verts.push(x3,y3,z3, c[0],c[1],c[2], nx,ny,nz);");
|
|
455
|
+
js.push(" verts.push(x1,y1,z1, c[0],c[1],c[2], nx,ny,nz);");
|
|
456
|
+
js.push(" verts.push(x3,y3,z3, c[0],c[1],c[2], nx,ny,nz);");
|
|
457
|
+
js.push(" verts.push(x4,y4,z4, c[0],c[1],c[2], nx,ny,nz);");
|
|
458
|
+
js.push(" }");
|
|
459
|
+
js.push(" for (var i = 0; i < BLOCKS.length; i++) {");
|
|
460
|
+
js.push(" var b = BLOCKS[i];");
|
|
461
|
+
js.push(" var x = b.x, y = b.y, z = b.z;");
|
|
462
|
+
js.push(" if (!self.hasBlock(x, y+1, z)) {");
|
|
463
|
+
js.push(" var ct = self.getBlockColor(b, 'top');");
|
|
464
|
+
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);");
|
|
465
|
+
js.push(" }");
|
|
466
|
+
js.push(" if (!self.hasBlock(x, y-1, z)) {");
|
|
467
|
+
js.push(" var cb = self.getBlockColor(b, 'bottom');");
|
|
468
|
+
js.push(" quad(x,y,z+1, x+1,y,z+1, x+1,y,z, x,y,z, 0,-1,0, cb);");
|
|
469
|
+
js.push(" }");
|
|
470
|
+
js.push(" if (!self.hasBlock(x, y, z-1)) {");
|
|
471
|
+
js.push(" var cn = self.getBlockColor(b, 'side');");
|
|
472
|
+
js.push(" quad(x,y,z, x+1,y,z, x+1,y+1,z, x,y+1,z, 0,0,-1, cn);");
|
|
473
|
+
js.push(" }");
|
|
474
|
+
js.push(" if (!self.hasBlock(x, y, z+1)) {");
|
|
475
|
+
js.push(" var cs = self.getBlockColor(b, 'side');");
|
|
476
|
+
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);");
|
|
477
|
+
js.push(" }");
|
|
478
|
+
js.push(" if (!self.hasBlock(x-1, y, z)) {");
|
|
479
|
+
js.push(" var cw = self.getBlockColor(b, 'side');");
|
|
480
|
+
js.push(" quad(x,y,z+1, x,y,z, x,y+1,z, x,y+1,z+1, -1,0,0, cw);");
|
|
481
|
+
js.push(" }");
|
|
482
|
+
js.push(" if (!self.hasBlock(x+1, y, z)) {");
|
|
483
|
+
js.push(" var ce = self.getBlockColor(b, 'side');");
|
|
484
|
+
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);");
|
|
485
|
+
js.push(" }");
|
|
486
|
+
js.push(" }");
|
|
487
|
+
js.push(" this.vertCount = verts.length / 9;");
|
|
488
|
+
js.push(" var gl = this.gl;");
|
|
489
|
+
js.push(" this.vbo = gl.createBuffer();");
|
|
490
|
+
js.push(" gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);");
|
|
491
|
+
js.push(" gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);");
|
|
492
|
+
js.push(" var aPos = gl.getAttribLocation(this.program, 'aPos');");
|
|
493
|
+
js.push(" var aColor = gl.getAttribLocation(this.program, 'aColor');");
|
|
494
|
+
js.push(" var aNormal = gl.getAttribLocation(this.program, 'aNormal');");
|
|
495
|
+
js.push(" gl.enableVertexAttribArray(aPos);");
|
|
496
|
+
js.push(" gl.enableVertexAttribArray(aColor);");
|
|
497
|
+
js.push(" gl.enableVertexAttribArray(aNormal);");
|
|
498
|
+
js.push(" gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 36, 0);");
|
|
499
|
+
js.push(" gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 36, 12);");
|
|
500
|
+
js.push(" gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, false, 36, 24);");
|
|
501
|
+
js.push(" },");
|
|
502
|
+
js.push("");
|
|
503
|
+
js.push(" resize: function () {");
|
|
504
|
+
js.push(" this.canvas.width = window.innerWidth;");
|
|
505
|
+
js.push(" this.canvas.height = window.innerHeight;");
|
|
506
|
+
js.push(" if (this.gl) this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);");
|
|
507
|
+
js.push(" },");
|
|
508
|
+
js.push("");
|
|
509
|
+
js.push(" bindInput: function () {");
|
|
510
|
+
js.push(" var self = this;");
|
|
511
|
+
js.push(" document.addEventListener('keydown', function (e) { self.keys[e.code] = true; });");
|
|
512
|
+
js.push(" document.addEventListener('keyup', function (e) { self.keys[e.code] = false; });");
|
|
513
|
+
js.push(" window.addEventListener('resize', function () { self.resize(); });");
|
|
514
|
+
js.push(" document.addEventListener('mousemove', function (e) {");
|
|
515
|
+
js.push(" if (!self.locked) return;");
|
|
516
|
+
js.push(" self.yaw += e.movementX * 0.003;");
|
|
517
|
+
js.push(" self.pitch -= e.movementY * 0.003;");
|
|
518
|
+
js.push(" if (self.pitch > 1.5) self.pitch = 1.5;");
|
|
519
|
+
js.push(" if (self.pitch < -1.5) self.pitch = -1.5;");
|
|
520
|
+
js.push(" });");
|
|
521
|
+
js.push(" document.addEventListener('pointerlockchange', function () {");
|
|
522
|
+
js.push(" self.locked = document.pointerLockElement === self.canvas;");
|
|
523
|
+
js.push(" var ov = document.getElementById('click-overlay');");
|
|
524
|
+
js.push(" ov.style.display = self.locked ? 'none' : 'flex';");
|
|
525
|
+
js.push(" });");
|
|
526
|
+
js.push(" document.getElementById('click-overlay').addEventListener('click', function () {");
|
|
527
|
+
js.push(" self.canvas.requestPointerLock();");
|
|
528
|
+
js.push(" });");
|
|
529
|
+
js.push(" },");
|
|
530
|
+
js.push("");
|
|
531
|
+
js.push(" getGroundY: function (x, z) {");
|
|
532
|
+
js.push(" var bx = Math.floor(x);");
|
|
533
|
+
js.push(" var bz = Math.floor(z);");
|
|
534
|
+
js.push(" for (var y = 30; y >= 0; y--) {");
|
|
535
|
+
js.push(" if (this.hasBlock(bx, y, bz)) return y + 1;");
|
|
536
|
+
js.push(" }");
|
|
537
|
+
js.push(" return 1;");
|
|
538
|
+
js.push(" },");
|
|
539
|
+
js.push("");
|
|
540
|
+
js.push(" update: function () {");
|
|
541
|
+
js.push(" if (!this.locked) return;");
|
|
542
|
+
js.push(" var spd = 0.08;");
|
|
543
|
+
js.push(" if (this.keys['ShiftLeft'] || this.keys['ShiftRight']) spd = 0.16;");
|
|
544
|
+
js.push(" var dx = 0, dz = 0;");
|
|
545
|
+
js.push(" var sy = Math.sin(this.yaw), cy = Math.cos(this.yaw);");
|
|
546
|
+
js.push(" if (this.keys['KeyW'] || this.keys['ArrowUp']) { dx -= sy * spd; dz -= cy * spd; }");
|
|
547
|
+
js.push(" if (this.keys['KeyS'] || this.keys['ArrowDown']) { dx += sy * spd; dz += cy * spd; }");
|
|
548
|
+
js.push(" if (this.keys['KeyA'] || this.keys['ArrowLeft']) { dx -= cy * spd; dz += sy * spd; }");
|
|
549
|
+
js.push(" if (this.keys['KeyD'] || this.keys['ArrowRight']) { dx += cy * spd; dz -= sy * spd; }");
|
|
550
|
+
js.push(" var nx = this.camX + dx;");
|
|
551
|
+
js.push(" var nz = this.camZ + dz;");
|
|
552
|
+
js.push(" var feet = Math.floor(this.camY - 1.6);");
|
|
553
|
+
js.push(" var bnx = Math.floor(nx);");
|
|
554
|
+
js.push(" var bnz = Math.floor(nz);");
|
|
555
|
+
js.push(" if (!this.hasBlock(bnx, feet, Math.floor(this.camZ)) && !this.hasBlock(bnx, feet+1, Math.floor(this.camZ))) {");
|
|
556
|
+
js.push(" this.camX = nx;");
|
|
557
|
+
js.push(" }");
|
|
558
|
+
js.push(" if (!this.hasBlock(Math.floor(this.camX), feet, bnz) && !this.hasBlock(Math.floor(this.camX), feet+1, bnz)) {");
|
|
559
|
+
js.push(" this.camZ = nz;");
|
|
560
|
+
js.push(" }");
|
|
561
|
+
js.push(" this.velY -= this.gravity;");
|
|
562
|
+
js.push(" this.camY += this.velY;");
|
|
563
|
+
js.push(" var gy = this.getGroundY(this.camX, this.camZ) + 1.6;");
|
|
564
|
+
js.push(" if (this.camY <= gy) {");
|
|
565
|
+
js.push(" this.camY = gy;");
|
|
566
|
+
js.push(" this.velY = 0;");
|
|
567
|
+
js.push(" this.onGround = true;");
|
|
568
|
+
js.push(" } else {");
|
|
569
|
+
js.push(" this.onGround = false;");
|
|
570
|
+
js.push(" }");
|
|
571
|
+
js.push(" if (this.keys['Space'] && this.onGround) {");
|
|
572
|
+
js.push(" this.velY = 0.18;");
|
|
573
|
+
js.push(" this.onGround = false;");
|
|
574
|
+
js.push(" }");
|
|
575
|
+
js.push(" },");
|
|
576
|
+
js.push("");
|
|
577
|
+
js.push(" perspective: function (fov, aspect, near, far) {");
|
|
578
|
+
js.push(" var f = 1.0 / Math.tan(fov / 2);");
|
|
579
|
+
js.push(" var nf = 1.0 / (near - far);");
|
|
580
|
+
js.push(" return new Float32Array([");
|
|
581
|
+
js.push(" f/aspect, 0, 0, 0,");
|
|
582
|
+
js.push(" 0, f, 0, 0,");
|
|
583
|
+
js.push(" 0, 0, (far+near)*nf, -1,");
|
|
584
|
+
js.push(" 0, 0, 2*far*near*nf, 0");
|
|
585
|
+
js.push(" ]);");
|
|
586
|
+
js.push(" },");
|
|
587
|
+
js.push("");
|
|
588
|
+
js.push(" lookAt: function () {");
|
|
589
|
+
js.push(" var cp = Math.cos(this.pitch), sp = Math.sin(this.pitch);");
|
|
590
|
+
js.push(" var cy = Math.cos(this.yaw), sy = Math.sin(this.yaw);");
|
|
591
|
+
js.push(" var fx = -sy * cp, fy = sp, fz = -cy * cp;");
|
|
592
|
+
js.push(" var len = Math.sqrt(fx*fx+fy*fy+fz*fz);");
|
|
593
|
+
js.push(" fx/=len; fy/=len; fz/=len;");
|
|
594
|
+
js.push(" var ux = 0, uy = 1, uz = 0;");
|
|
595
|
+
js.push(" var rx = fy*uz - fz*uy, ry = fz*ux - fx*uz, rz = fx*uy - fy*ux;");
|
|
596
|
+
js.push(" len = Math.sqrt(rx*rx+ry*ry+rz*rz);");
|
|
597
|
+
js.push(" rx/=len; ry/=len; rz/=len;");
|
|
598
|
+
js.push(" ux = ry*fz - rz*fy; uy = rz*fx - rx*fz; uz = rx*fy - ry*fx;");
|
|
599
|
+
js.push(" var tx = -rx*this.camX - ry*this.camY - rz*this.camZ;");
|
|
600
|
+
js.push(" var ty = -ux*this.camX - uy*this.camY - uz*this.camZ;");
|
|
601
|
+
js.push(" var tz = fx*this.camX + fy*this.camY + fz*this.camZ;");
|
|
602
|
+
js.push(" return new Float32Array([");
|
|
603
|
+
js.push(" rx, ux, -fx, 0,");
|
|
604
|
+
js.push(" ry, uy, -fy, 0,");
|
|
605
|
+
js.push(" rz, uz, -fz, 0,");
|
|
606
|
+
js.push(" tx, ty, tz, 1");
|
|
607
|
+
js.push(" ]);");
|
|
608
|
+
js.push(" },");
|
|
609
|
+
js.push("");
|
|
610
|
+
js.push(" render: function () {");
|
|
611
|
+
js.push(" var gl = this.gl;");
|
|
612
|
+
js.push(" gl.clearColor(0.53, 0.81, 0.92, 1.0);");
|
|
613
|
+
js.push(" gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);");
|
|
614
|
+
js.push(" gl.enable(gl.DEPTH_TEST);");
|
|
615
|
+
js.push(" gl.enable(gl.CULL_FACE);");
|
|
616
|
+
js.push(" gl.cullFace(gl.BACK);");
|
|
617
|
+
js.push(" var aspect = this.canvas.width / this.canvas.height;");
|
|
618
|
+
js.push(" var proj = this.perspective(1.2, aspect, 0.1, 200.0);");
|
|
619
|
+
js.push(" var view = this.lookAt();");
|
|
620
|
+
js.push(" gl.uniformMatrix4fv(this.uProj, false, proj);");
|
|
621
|
+
js.push(" gl.uniformMatrix4fv(this.uView, false, view);");
|
|
622
|
+
js.push(" gl.uniform3f(this.uCamPos, this.camX, this.camY, this.camZ);");
|
|
623
|
+
js.push(" gl.drawArrays(gl.TRIANGLES, 0, this.vertCount);");
|
|
624
|
+
js.push(" this.updateHUD();");
|
|
625
|
+
js.push(" },");
|
|
626
|
+
js.push("");
|
|
627
|
+
js.push(" getStandingBlock: function () {");
|
|
628
|
+
js.push(" var bx = Math.floor(this.camX);");
|
|
629
|
+
js.push(" var bz = Math.floor(this.camZ);");
|
|
630
|
+
js.push(" var by = Math.floor(this.camY - 1.7);");
|
|
631
|
+
js.push(" var b = this.blockMap[bx + ',' + by + ',' + bz];");
|
|
632
|
+
js.push(" return b ? b.t : 'air';");
|
|
633
|
+
js.push(" },");
|
|
634
|
+
js.push("");
|
|
635
|
+
js.push(" updateHUD: function () {");
|
|
636
|
+
js.push(" var h = document.getElementById('hud-info');");
|
|
637
|
+
js.push(" if (!h) return;");
|
|
638
|
+
js.push(" var standing = this.getStandingBlock();");
|
|
639
|
+
js.push(" var sprinting = this.keys['ShiftLeft'] || this.keys['ShiftRight'];");
|
|
640
|
+
js.push(" var tris = Math.floor(this.vertCount / 3);");
|
|
641
|
+
js.push(" h.innerHTML = '<div class=\"hud-title\">CaG Engine</div>' +");
|
|
642
|
+
js.push(" '<div>' + INFO.ID + ' v' + INFO.version + '</div>' +");
|
|
643
|
+
js.push(" '<div class=\"hud-sep\"></div>' +");
|
|
644
|
+
js.push(" '<div>FPS: ' + this.fps + ' | Tris: ' + tris.toLocaleString() + '</div>' +");
|
|
645
|
+
js.push(" '<div>Blocks: ' + BLOCKS.length.toLocaleString() + '</div>' +");
|
|
646
|
+
js.push(" '<div class=\"hud-sep\"></div>' +");
|
|
647
|
+
js.push(" '<div>X: ' + this.camX.toFixed(1) + ' Y: ' + this.camY.toFixed(1) + ' Z: ' + this.camZ.toFixed(1) + '</div>' +");
|
|
648
|
+
js.push(" '<div>Standing: ' + standing + (sprinting ? ' [SPRINT]' : '') + '</div>';");
|
|
649
|
+
js.push(" },");
|
|
650
|
+
js.push("");
|
|
651
|
+
js.push(" loop: function () {");
|
|
652
|
+
js.push(" this.update();");
|
|
653
|
+
js.push(" this.render();");
|
|
654
|
+
js.push(" this.frames++;");
|
|
655
|
+
js.push(" var now = performance.now();");
|
|
656
|
+
js.push(" if (now - this.lastFps >= 1000) {");
|
|
657
|
+
js.push(" this.fps = this.frames;");
|
|
658
|
+
js.push(" this.frames = 0;");
|
|
659
|
+
js.push(" this.lastFps = now;");
|
|
660
|
+
js.push(" }");
|
|
661
|
+
js.push(" requestAnimationFrame(this.loop.bind(this));");
|
|
662
|
+
js.push(" }");
|
|
663
|
+
js.push("};");
|
|
664
|
+
js.push("");
|
|
665
|
+
js.push("var bar = document.getElementById('bar-inner');");
|
|
666
|
+
js.push("var status = document.getElementById('load-status');");
|
|
667
|
+
js.push("bar.style.width = '10%';");
|
|
668
|
+
js.push("status.textContent = 'Initializing CaG Engine...';");
|
|
669
|
+
js.push("setTimeout(function () {");
|
|
670
|
+
js.push(" bar.style.width = '25%';");
|
|
671
|
+
js.push(" status.textContent = 'Parsing project data...';");
|
|
672
|
+
js.push("}, 300);");
|
|
673
|
+
js.push("setTimeout(function () {");
|
|
674
|
+
js.push(" bar.style.width = '45%';");
|
|
675
|
+
js.push(" status.textContent = 'Generating terrain (' + BLOCKS.length.toLocaleString() + ' blocks)...';");
|
|
676
|
+
js.push("}, 600);");
|
|
677
|
+
js.push("setTimeout(function () {");
|
|
678
|
+
js.push(" bar.style.width = '65%';");
|
|
679
|
+
js.push(" status.textContent = 'Building mesh geometry...';");
|
|
680
|
+
js.push("}, 900);");
|
|
681
|
+
js.push("setTimeout(function () {");
|
|
682
|
+
js.push(" bar.style.width = '80%';");
|
|
683
|
+
js.push(" status.textContent = 'Compiling CaG shaders...';");
|
|
684
|
+
js.push("}, 1200);");
|
|
685
|
+
js.push("setTimeout(function () {");
|
|
686
|
+
js.push(" bar.style.width = '95%';");
|
|
687
|
+
js.push(" status.textContent = 'Preparing renderer...';");
|
|
688
|
+
js.push("}, 1500);");
|
|
689
|
+
js.push("setTimeout(function () {");
|
|
690
|
+
js.push(" bar.style.width = '100%';");
|
|
691
|
+
js.push(" status.textContent = 'Ready';");
|
|
692
|
+
js.push(" status.style.color = '#4ecca3';");
|
|
693
|
+
js.push("}, 1800);");
|
|
694
|
+
js.push("setTimeout(function () { cag.init(); }, 2200);");
|
|
695
|
+
|
|
696
|
+
var html = "<!DOCTYPE html>\n<html>\n<head>\n";
|
|
697
|
+
html += "<meta charset='utf-8'>\n";
|
|
698
|
+
html += "<title>" + info.ID + " - CaG Engine</title>\n";
|
|
699
|
+
html += "<style>\n" + css + "\n</style>\n";
|
|
700
|
+
html += "</head>\n<body>\n";
|
|
701
|
+
html += "<div id='loading'>\n";
|
|
702
|
+
html += " <h1>CaG</h1>\n";
|
|
703
|
+
html += " <h2>" + info.ID + "</h2>\n";
|
|
704
|
+
html += " <div id='load-status'>Starting...</div>\n";
|
|
705
|
+
html += " <div id='bar-outer'><div id='bar-inner'></div></div>\n";
|
|
706
|
+
html += " <div class='version-tag'>v" + (info.version || "1.0.0") + "</div>\n";
|
|
707
|
+
html += "</div>\n";
|
|
708
|
+
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";
|
|
709
|
+
html += "<div id='crosshair'></div>\n";
|
|
710
|
+
html += "<div id='hud'><div id='hud-box'><div id='hud-info'></div></div></div>\n";
|
|
711
|
+
html += "<div id='controls-hint'><b>WASD</b> Move <b>Mouse</b> Look <b>Space</b> Jump <b>Shift</b> Sprint <b>F11</b> Fullscreen <b>Esc</b> Release</div>\n";
|
|
712
|
+
html += "<canvas id='cag-canvas'></canvas>\n";
|
|
713
|
+
html += "<script>\n" + js.join("\n") + "\n</script>\n";
|
|
714
|
+
html += "</body>\n</html>";
|
|
715
|
+
|
|
716
|
+
return html;
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
ExeBuilder.prototype.generateWorldBlocks = function () {
|
|
720
|
+
var codeFiles = this.engine.getCodeFiles();
|
|
721
|
+
var topLayer = "grass";
|
|
722
|
+
var fillLayer = "dirt";
|
|
723
|
+
var bottomLayer = "stone";
|
|
724
|
+
var size = 32;
|
|
725
|
+
var seed = 54321;
|
|
726
|
+
var waterLevel = 3;
|
|
727
|
+
var hasWater = false;
|
|
728
|
+
|
|
729
|
+
for (var i = 0; i < codeFiles.length; i++) {
|
|
730
|
+
var content = fs.readFileSync(codeFiles[i], "utf-8");
|
|
731
|
+
var lines = content.split("\n");
|
|
732
|
+
for (var j = 0; j < lines.length; j++) {
|
|
733
|
+
var line = lines[j].trim();
|
|
734
|
+
if (line.indexOf("top") !== -1 && line.indexOf("layer") !== -1 && line.indexOf("=") !== -1) {
|
|
735
|
+
var eqIdx = line.lastIndexOf("=");
|
|
736
|
+
var val = line.substring(eqIdx + 1).trim();
|
|
737
|
+
if (val) topLayer = val.toLowerCase();
|
|
738
|
+
}
|
|
739
|
+
if (line.indexOf("fill") !== -1 && line.indexOf("layer") !== -1 && line.indexOf("=") !== -1) {
|
|
740
|
+
var fIdx = line.lastIndexOf("=");
|
|
741
|
+
var fVal = line.substring(fIdx + 1).trim();
|
|
742
|
+
if (fVal) fillLayer = fVal.toLowerCase();
|
|
743
|
+
}
|
|
744
|
+
if (line.indexOf("bottom") !== -1 && line.indexOf("layer") !== -1 && line.indexOf("=") !== -1) {
|
|
745
|
+
var bIdx = line.lastIndexOf("=");
|
|
746
|
+
var bVal = line.substring(bIdx + 1).trim();
|
|
747
|
+
if (bVal) bottomLayer = bVal.toLowerCase();
|
|
748
|
+
}
|
|
749
|
+
if (line.indexOf("water") !== -1) {
|
|
750
|
+
hasWater = true;
|
|
751
|
+
}
|
|
752
|
+
if (line.indexOf("size") !== -1 && line.indexOf("=") !== -1) {
|
|
753
|
+
var sIdx = line.lastIndexOf("=");
|
|
754
|
+
var sVal = parseInt(line.substring(sIdx + 1).trim(), 10);
|
|
755
|
+
if (!isNaN(sVal) && sVal >= 8 && sVal <= 128) size = sVal;
|
|
756
|
+
}
|
|
757
|
+
if (line.indexOf("seed") !== -1 && line.indexOf("=") !== -1) {
|
|
758
|
+
var sdIdx = line.lastIndexOf("=");
|
|
759
|
+
var sdVal = parseInt(line.substring(sdIdx + 1).trim(), 10);
|
|
760
|
+
if (!isNaN(sdVal)) seed = sdVal;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
var blocks = [];
|
|
766
|
+
|
|
767
|
+
var noise = function (x, z, s, scale) {
|
|
768
|
+
var nx = x / scale;
|
|
769
|
+
var nz = z / scale;
|
|
770
|
+
var a = Math.sin(nx * 12.9898 + nz * 78.233 + s) * 43758.5453;
|
|
771
|
+
return a - Math.floor(a);
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
var smoothHeight = function (x, z) {
|
|
775
|
+
var h1 = noise(x, z, seed, 8.0) * 4;
|
|
776
|
+
var h2 = noise(x, z, seed + 100, 16.0) * 6;
|
|
777
|
+
var h3 = noise(x, z, seed + 200, 4.0) * 2;
|
|
778
|
+
var h4 = noise(x + 0.5, z + 0.5, seed + 300, 12.0) * 3;
|
|
779
|
+
|
|
780
|
+
var avg = 0;
|
|
781
|
+
var count = 0;
|
|
782
|
+
for (var dx = -1; dx <= 1; dx++) {
|
|
783
|
+
for (var dz = -1; dz <= 1; dz++) {
|
|
784
|
+
var n1 = noise(x + dx, z + dz, seed, 8.0) * 4;
|
|
785
|
+
var n2 = noise(x + dx, z + dz, seed + 100, 16.0) * 6;
|
|
786
|
+
avg += n1 + n2;
|
|
787
|
+
count++;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
avg = avg / count;
|
|
791
|
+
|
|
792
|
+
var raw = (h1 + h2 + h3 + h4) * 0.4 + avg * 0.6;
|
|
793
|
+
return Math.max(1, Math.min(Math.floor(raw), 12));
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
for (var x = 0; x < size; x++) {
|
|
797
|
+
for (var z = 0; z < size; z++) {
|
|
798
|
+
var height = smoothHeight(x, z);
|
|
799
|
+
for (var y = 0; y <= height; y++) {
|
|
800
|
+
var blockType;
|
|
801
|
+
if (y === height) {
|
|
802
|
+
blockType = topLayer;
|
|
803
|
+
} else if (y === 0) {
|
|
804
|
+
blockType = bottomLayer;
|
|
805
|
+
} else if (y >= height - 1) {
|
|
806
|
+
blockType = topLayer === "grass" ? fillLayer : topLayer;
|
|
807
|
+
} else {
|
|
808
|
+
blockType = fillLayer;
|
|
809
|
+
}
|
|
810
|
+
blocks.push({ x: x, y: y, z: z, t: blockType });
|
|
811
|
+
}
|
|
812
|
+
if (hasWater && height < waterLevel) {
|
|
813
|
+
for (var wy = height + 1; wy <= waterLevel; wy++) {
|
|
814
|
+
blocks.push({ x: x, y: wy, z: z, t: "water" });
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return blocks;
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
ExeBuilder.prototype.generateMacApp = function (html, appPath) {
|
|
824
|
+
var contentsDir = path.join(appPath, 'Contents');
|
|
825
|
+
var macosDir = path.join(contentsDir, 'MacOS');
|
|
826
|
+
var resourcesDir = path.join(contentsDir, 'Resources');
|
|
827
|
+
fs.mkdirSync(macosDir, { recursive: true });
|
|
828
|
+
fs.mkdirSync(resourcesDir, { recursive: true });
|
|
829
|
+
fs.writeFileSync(path.join(resourcesDir, 'game.html'), html);
|
|
830
|
+
var launcher = '#!/bin/bash\n';
|
|
831
|
+
launcher += 'DIR="$(cd "$(dirname "$0")" && pwd)"\n';
|
|
832
|
+
launcher += 'HTML="$DIR/../Resources/game.html"\n';
|
|
833
|
+
launcher += 'if [ -d "/Applications/Google Chrome.app" ]; then\n';
|
|
834
|
+
launcher += ' open -a "Google Chrome" --args --app="file://$HTML" --window-size=1280,720 --disable-extensions --no-first-run\n';
|
|
835
|
+
launcher += 'elif [ -d "/Applications/Microsoft Edge.app" ]; then\n';
|
|
836
|
+
launcher += ' open -a "Microsoft Edge" --args --app="file://$HTML" --window-size=1280,720 --disable-extensions --no-first-run\n';
|
|
837
|
+
launcher += 'else\n';
|
|
838
|
+
launcher += ' open "$HTML"\n';
|
|
839
|
+
launcher += 'fi\n';
|
|
840
|
+
var launcherPath = path.join(macosDir, this.projectName);
|
|
841
|
+
fs.writeFileSync(launcherPath, launcher);
|
|
842
|
+
try { fs.chmodSync(launcherPath, 0o755); } catch (e) {}
|
|
843
|
+
var plist = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
|
844
|
+
plist += '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
|
|
845
|
+
plist += '<plist version="1.0">\n<dict>\n';
|
|
846
|
+
plist += ' <key>CFBundleExecutable</key>\n <string>' + this.projectName + '</string>\n';
|
|
847
|
+
plist += ' <key>CFBundleName</key>\n <string>' + this.info.ID + '</string>\n';
|
|
848
|
+
plist += ' <key>CFBundleIdentifier</key>\n <string>' + this.info.ID + '</string>\n';
|
|
849
|
+
plist += ' <key>CFBundleVersion</key>\n <string>' + (this.info.version || '1.0.0') + '</string>\n';
|
|
850
|
+
plist += ' <key>CFBundlePackageType</key>\n <string>APPL</string>\n';
|
|
851
|
+
plist += '</dict>\n</plist>\n';
|
|
852
|
+
fs.writeFileSync(path.join(contentsDir, 'Info.plist'), plist);
|
|
853
|
+
};
|
|
854
|
+
|
|
855
|
+
ExeBuilder.prototype.generateLinuxApp = function (html, outputPath) {
|
|
856
|
+
var b64 = Buffer.from(html, 'utf-8').toString('base64');
|
|
857
|
+
var script = '#!/bin/bash\n';
|
|
858
|
+
script += 'TEMP_DIR=$(mktemp -d /tmp/cag_XXXXXX)\n';
|
|
859
|
+
script += 'HTML_PATH="$TEMP_DIR/game.html"\n';
|
|
860
|
+
script += 'echo "' + b64 + '" | base64 -d > "$HTML_PATH"\n';
|
|
861
|
+
script += 'cleanup() { rm -rf "$TEMP_DIR"; }\n';
|
|
862
|
+
script += 'trap cleanup EXIT\n';
|
|
863
|
+
script += 'if command -v google-chrome &>/dev/null; then\n';
|
|
864
|
+
script += ' google-chrome --app="file://$HTML_PATH" --window-size=1280,720 --disable-extensions --no-first-run 2>/dev/null\n';
|
|
865
|
+
script += 'elif command -v chromium-browser &>/dev/null; then\n';
|
|
866
|
+
script += ' chromium-browser --app="file://$HTML_PATH" --window-size=1280,720 --disable-extensions --no-first-run 2>/dev/null\n';
|
|
867
|
+
script += 'elif command -v chromium &>/dev/null; then\n';
|
|
868
|
+
script += ' chromium --app="file://$HTML_PATH" --window-size=1280,720 --disable-extensions --no-first-run 2>/dev/null\n';
|
|
869
|
+
script += 'elif command -v microsoft-edge &>/dev/null; then\n';
|
|
870
|
+
script += ' microsoft-edge --app="file://$HTML_PATH" --window-size=1280,720 --disable-extensions --no-first-run 2>/dev/null\n';
|
|
871
|
+
script += 'else\n';
|
|
872
|
+
script += ' xdg-open "$HTML_PATH" 2>/dev/null || open "$HTML_PATH"\n';
|
|
873
|
+
script += 'fi\n';
|
|
874
|
+
fs.writeFileSync(outputPath, script);
|
|
875
|
+
try { fs.chmodSync(outputPath, 0o755); } catch (e) {}
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
ExeBuilder.prototype.cleanup = function () {
|
|
879
|
+
this.removeDirectory(this.tempDir);
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
ExeBuilder.prototype.removeDirectory = function (dir) {
|
|
883
|
+
if (!fs.existsSync(dir)) return;
|
|
884
|
+
var entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
885
|
+
for (var i = 0; i < entries.length; i++) {
|
|
886
|
+
var fullPath = path.join(dir, entries[i].name);
|
|
887
|
+
if (entries[i].isDirectory()) {
|
|
888
|
+
this.removeDirectory(fullPath);
|
|
889
|
+
} else {
|
|
890
|
+
fs.unlinkSync(fullPath);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
fs.rmdirSync(dir);
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
ExeBuilder.prototype.getFileSize = function (filePath) {
|
|
897
|
+
if (!fs.existsSync(filePath)) return 0;
|
|
898
|
+
return fs.statSync(filePath).size;
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
ExeBuilder.prototype.getDirectorySize = function (dir) {
|
|
902
|
+
if (!fs.existsSync(dir)) return 0;
|
|
903
|
+
var total = 0;
|
|
904
|
+
var entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
905
|
+
for (var i = 0; i < entries.length; i++) {
|
|
906
|
+
var fullPath = path.join(dir, entries[i].name);
|
|
907
|
+
if (entries[i].isDirectory()) {
|
|
908
|
+
total += this.getDirectorySize(fullPath);
|
|
909
|
+
} else {
|
|
910
|
+
total += fs.statSync(fullPath).size;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
return total;
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
ExeBuilder.prototype.formatSize = function (bytes) {
|
|
917
|
+
if (bytes < 1024) return bytes + " B";
|
|
918
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
919
|
+
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
ExeBuilder.prototype.detectPlatform = function () {
|
|
923
|
+
var p = process.platform;
|
|
924
|
+
if (p === "win32") return "win";
|
|
925
|
+
if (p === "darwin") return "macos";
|
|
926
|
+
return "linux";
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
module.exports = ExeBuilder;
|