Skip to content

Commit f9ad124

Browse files
authored
refine (#483)
1 parent 83c7faa commit f9ad124

12 files changed

Lines changed: 263 additions & 26831 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ packages/cocos-cli-types/**/*
2626

2727
# static
2828
static/tools/
29+
static/web/scene-bundle.js
30+
static/web/scene-bundle.js.map
2931

3032
# 构建文件
3133
/dist

src/core/engine/editor-extends/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ export { walkProperties } from './missing-reporter/object-walker';
1111

1212
import utils from '../../base/utils';
1313
import EventEmitter from 'events';
14+
if (!EventEmitter.prototype.off) {
15+
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
16+
}
1417
import ScriptManager from './manager/script';
1518
import NodeManager from './manager/node';
1619
import ComponentManager from './manager/component';

src/core/scene/scene-process/scene-runtime.ts renamed to src/core/scene/scene-process/engine-bootstrap.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,14 @@ export const Service = DecoratorService;
2020
declare const cc: any;
2121

2222
export async function startup(options: {
23-
enginePath: string;
2423
projectPath: string;
2524
serverURL: string;
26-
startScene: any;
2725
}) {
2826
const defaultConfig = await fetch('/scripting/engine/game-config');
2927
const config = await defaultConfig.json();
3028
const modules = await fetch('/scripting/engine/modules');
3129
const features = (await modules.json()) as string[];
32-
const { projectPath, serverURL, startScene } = options;
30+
const { projectPath, serverURL } = options;
3331

3432
if (typeof window !== 'undefined') {
3533
(window as any).__CC_PROJECT_PATH__ = projectPath;
@@ -105,23 +103,5 @@ export async function startup(options: {
105103

106104
await cc.game.run(async () => {
107105
cc.game.pause();
108-
const json = startScene;
109-
// load scene
110-
cc.assetManager.loadWithJson(json, { assetId: json[1]._id },
111-
// 进度条
112-
(completedCount: number, totalCount: number) => {
113-
//
114-
}, (error: Error | null, sceneAsset: any) => {
115-
if (error) {
116-
cc.error(error);
117-
return;
118-
}
119-
const scene = sceneAsset.scene;
120-
scene._name = sceneAsset._name;
121-
cc.director.runSceneImmediate(scene, () => {
122-
cc.game.resume();
123-
});
124-
});
125106
});
126-
await cc.game.resume();
127107
}

src/core/scene/scene.middleware.ts

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,44 @@ import fse from 'fs-extra';
55

66
export default {
77
get: [
8+
{
9+
url: '/engine/read-file-sync',
10+
async handler(req: Request, res: Response) {
11+
let filePath = req.query.path as string;
12+
if (!filePath) {
13+
return res.status(400).send('Path is required');
14+
}
15+
16+
// Normalize path to fix mixed slashes on Windows
17+
filePath = path.normalize(filePath);
18+
19+
if (!(await fse.pathExists(filePath))) {
20+
// Fallback for .wasm.wasm -> .wasm if the double extension file is missing
21+
if (filePath.endsWith('.wasm.wasm')) {
22+
const fallbackPath = filePath.slice(0, -5);
23+
if (await fse.pathExists(fallbackPath)) {
24+
filePath = fallbackPath;
25+
}
26+
}
27+
}
28+
29+
if (await fse.pathExists(filePath)) {
30+
const content = await fse.readFile(filePath);
31+
res.status(200).send(content);
32+
} else {
33+
res.status(404).send('File not found: ' + filePath);
34+
}
35+
}
36+
},
37+
{
38+
// TODO 这里后续需要改引擎 wasm/wasm-nodejs.ts 的写法,改成向服务器请求数据
39+
url: '/engine/query-engine-info',
40+
async handler(req: Request, res: Response) {
41+
const { Engine } = await import('../engine');
42+
const engineInfo = Engine.getInfo();
43+
res.status(200).send(engineInfo);
44+
},
45+
},
846
{
947
// TODO 这里后续需要改引擎 wasm/wasm-nodejs.ts 的写法,改成向服务器请求数据
1048
url: '/engine_external/',
@@ -23,9 +61,9 @@ export default {
2361
},
2462
},
2563
{
26-
url: '/query-extname/:uuid',
64+
url: /^\/query-extname\/(.+)$/,
2765
async handler(req: Request, res: Response) {
28-
const uuid = req.params.uuid;
66+
const uuid = req.params[0];
2967
const { assetManager } = await import('../assets');
3068
const assetInfo = assetManager.queryAssetInfo(uuid);
3169
if (assetInfo && assetInfo.library['.bin'] && Object.keys(assetInfo.library).length === 1) {
@@ -36,9 +74,9 @@ export default {
3674
},
3775
},
3876
{
39-
url: '/query-asset-info/:uuid',
77+
url: /^\/query-asset-info\/(.+)$/,
4078
async handler(req: Request, res: Response) {
41-
const uuid = req.params.uuid;
79+
const uuid = req.params[0];
4280
const { assetManager } = await import('../assets');
4381
const assetInfo = assetManager.queryAssetInfo(uuid);
4482
if (assetInfo) {
@@ -61,26 +99,6 @@ export default {
6199
}
62100
},
63101
},
64-
{
65-
url: '/scene/:uuid.json',
66-
async handler(req: Request, res: Response, next: NextFunction) {
67-
const scene_uuid = req.params.uuid;
68-
const { assetManager } = await import('../assets');
69-
const assetInfo = assetManager.queryAssetInfo(scene_uuid);
70-
if (assetInfo && assetInfo.library['.json']) {
71-
const filepath = assetInfo.library['.json'];
72-
if (filepath) {
73-
res.sendFile(filepath);
74-
}
75-
else {
76-
return next(new Error(`Scene not found: ${scene_uuid}`));
77-
}
78-
}
79-
else {
80-
return next(new Error(`Scene not found: ${scene_uuid}`));
81-
}
82-
},
83-
},
84102
{
85103
// Serve library assets by UUID - try asset database first,
86104
// then fall back to library directories on disk

src/core/scene/scripting.middleware.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export default {
2424
packImportMapURL: `/scripting/x/${facet.packImportMapURL}`,
2525
packResolutionDetailMapURL: `/scripting/x/${facet.packResolutionDetailMapURL}`,
2626
engineDistPath: `/scripting/engine/${engineDistRelPath}`,
27-
globalImportMap: await facet.getGlobalImportMap(),
2827
projectPath: scripting.projectPath.replace(/\\/g, '/'),
2928
enginePath: enginePath.replace(/\\/g, '/'),
3029
serverURL: serverBaseUrl
@@ -97,7 +96,7 @@ export default {
9796
async handler(req: Request, res: Response) {
9897
const { getPreviewFacet } = await import('../scripting/programming/FacetInstance');
9998
const facet = getPreviewFacet();
100-
const importMap = facet.getGlobalImportMap();
99+
const importMap = await facet.getGlobalImportMap();
101100
console.log(`[Preview Server] Global import map:`, JSON.stringify(importMap, null, 2).substring(0, 500));
102101
res.json(importMap);
103102
},

static/web/boot.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* global window, document, System, globalThis, fetch */
2+
/* eslint-disable quotes */
3+
const env = window.WebEnv;
4+
5+
(async function () {
6+
try {
7+
await import("/static/web/polyfills.bundle.js");
8+
await import("/scripting/systemjs/system.js");
9+
await import("/scripting/systemjs/extras/named-register.js");
10+
11+
// Inject import maps. System.import naturally waits for them!
12+
const sources = [
13+
`${env.engineDistPath}/import-map.json`,
14+
env.packImportMapURL,
15+
'/scripting/import-map-global'
16+
];
17+
sources.forEach(src => {
18+
const script = document.createElement('script');
19+
Object.assign(script, {
20+
type: 'systemjs-importmap',
21+
src
22+
});
23+
document.head.appendChild(script);
24+
});
25+
26+
System.setResolutionDetailMapCallback(function () {
27+
const url = new URL(env.packResolutionDetailMapURL, env.serverURL);
28+
return fetch(url).then(function (response) {
29+
return response.json();
30+
}).then(function (json) {
31+
return { json, url: url.href };
32+
});
33+
});
34+
35+
await import("/static/web/editor-stub-preload.js");
36+
await import(`${env.engineDistPath}/bundled/index.js`);
37+
38+
const _originalSystem = System;
39+
console.log('[Scene] loading scene bundle');
40+
// SystemJS natively awaits the attached import maps above
41+
const SceneBundle = await System.import('/static/web/scene-bundle.js?t=' + Date.now());
42+
const { startup } = SceneBundle;
43+
44+
globalThis.System = _originalSystem;
45+
await startup({
46+
enginePath: env.enginePath,
47+
projectPath: env.projectPath,
48+
serverURL: env.serverURL
49+
});
50+
console.log('Cocos Engine and Scene Services loaded successfully');
51+
} catch (err) {
52+
console.error('Failed to load Cocos Engine or Services:', err.stack || err);
53+
}
54+
})();

static/web/editor-stub-preload.js

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
/* global window */
22

33
window.CC_EDITOR = true;
4+
const serverUrl = window.WebEnv.serverURL;
45

56
window.Editor = {
67
Message: {
78
request: async function (target, method, uuid) {
89
if (method === 'query-asset-info') {
9-
const currentUrl = window.location.origin;
10-
return await fetch(`${currentUrl}/query-asset-info/${uuid}`)
10+
return await fetch(`${serverUrl}/query-asset-info/${uuid}`)
11+
.then(function (r) { return r.json(); })
12+
.catch(function () { return ''; });
13+
} else if (method === 'query-engine-info') {
14+
return await fetch(`${serverUrl}/engine/query-engine-info`)
1115
.then(function (r) { return r.json(); })
1216
.catch(function () { return ''; });
1317
}
@@ -16,9 +20,49 @@ window.Editor = {
1620
},
1721
};
1822

23+
if (typeof window.require === 'undefined') {
24+
const fsMock = {
25+
readFile: function (filePath) {
26+
const requestUrl = `${serverUrl}/engine/read-file-sync?path=${encodeURIComponent(filePath)}`;
27+
return fetch(requestUrl).then(function (res) {
28+
if (res.ok) {
29+
return res.arrayBuffer();
30+
}
31+
throw new Error('Failed to read file: ' + filePath);
32+
});
33+
},
34+
readFileSync: function (filePath) {
35+
const requestUrl = `${serverUrl}/engine/read-file-sync?path=${encodeURIComponent(filePath)}`;
36+
const xhr = new XMLHttpRequest();
37+
xhr.open('GET', requestUrl, false); // synchronous
38+
xhr.overrideMimeType('text/plain; charset=x-user-defined');
39+
xhr.send(null);
40+
41+
if (xhr.status === 200) {
42+
const val = xhr.responseText;
43+
const len = val.length;
44+
const buf = new Uint8Array(len);
45+
for (let i = 0; i < len; i++) {
46+
buf[i] = val.charCodeAt(i) & 0xff;
47+
}
48+
return buf;
49+
}
50+
throw new Error('Failed to read file synchronously: ' + filePath);
51+
}
52+
};
53+
54+
window.require = function (name) {
55+
if (name === 'fs' || name === 'fs-extra') {
56+
return fsMock;
57+
}
58+
throw new Error('Module ' + name + ' not found in editor-stub-preload require mock');
59+
};
60+
}
61+
1962
window.EditorExtends = {
2063
emit: function () { },
2164
on: function () { },
65+
off: function () { },
2266
removeListener: function () { },
2367
UuidUtils: {
2468
uuid: function () { return ''; },
@@ -28,18 +72,54 @@ window.EditorExtends = {
2872
isUuid: function () { return false; },
2973
},
3074
Component: {
75+
allow: false,
3176
addMenu: function () { },
3277
removeMenu: function () { },
78+
getMenus: function () { return []; },
3379
add: function () { },
3480
remove: function () { },
81+
clear: function () { },
82+
getComponent: function () { return null; },
83+
getComponentFromPath: function () { return null; },
84+
getPathFromUuid: function () { return ''; },
85+
getComponents: function () { return {}; },
86+
changeUUID: function () { },
87+
emit: function () { },
88+
on: function () { },
89+
off: function () { },
90+
removeListener: function () { },
3591
},
3692
Node: {
93+
allow: false,
3794
add: function () { },
3895
remove: function () { },
96+
clear: function () { },
97+
updateNodeName: function () { },
3998
getNode: function () { return null; },
99+
getNodeByPath: function () { return null; },
100+
getNodePath: function () { return ''; },
101+
getNodeUuidByPath: function () { return null; },
102+
getNodeByPathOrThrow: function () { throw new Error('Not implemented'); },
103+
getNodeUuidByPathOrThrow: function () { throw new Error('Not implemented'); },
104+
getNodes: function () { return {}; },
105+
getNodesByAsset: function () { return []; },
106+
getNodesInScene: function () { return {}; },
107+
changeNodeUUID: function () { },
108+
emit: function () { },
109+
on: function () { },
110+
off: function () { },
111+
removeListener: function () { },
112+
},
113+
Script: {
114+
allow: false,
115+
add: function () { },
116+
remove: function () { },
117+
getCtors: function () { return []; },
40118
emit: function () { },
119+
on: function () { },
120+
off: function () { },
121+
removeListener: function () { },
41122
},
42-
Script: { allow: false },
43123
MissingReporter: {
44124
classInstance: (function () {
45125
const finder = function (type, data, owner, propName) {

0 commit comments

Comments
 (0)