mirror of
https://github.com/HappyLifeOk/cc-3-8-x-mcp.git
synced 2026-06-10 09:46:47 +00:00
fix(cli): 删节点/组件后清理孤儿元素的 cc.Asset 引用,避免 build 404
remove-node / remove-component 保留孤儿元素(保持其他 __id__ 稳定)的策略下, 残留的 cc.Asset uuid 引用会被 bundle build 扫整个 data 数组撞到、算入依赖图, 运行时拉不存在的资源触发 404。新增 clearOrphanAssetRefs,删完后清理。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -119,6 +119,57 @@ function disconnectSubtree(elements, nodeId) {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 孤儿元素 cc.Asset 引用清理 ──────────────────────────────
|
||||
|
||||
/**
|
||||
* 清除元素里所有 cc.Asset 引用字段(含 `{__uuid__, __expectedType__}` 的对象,
|
||||
* 或全部由这类对象组成的数组),把对象置 null、数组置 []。
|
||||
*
|
||||
* 用于 remove-node / remove-component:cli 保留孤儿元素(保持其他 __id__ 稳定)的
|
||||
* 策略本身正确,但孤儿元素里残留的 cc.Asset uuid 引用会被 bundle build 扫整个
|
||||
* data 数组时撞到、算入依赖图,运行时拉不存在的资源触发 404
|
||||
* (典型现象:`GET /assets/<bundle>/import/<uuid>.json 404`)。
|
||||
*
|
||||
* 只处理顶层字段——cc.Asset 引用一般在第一层(_spriteFrame / _defaultClip / _clips /
|
||||
* _font / _skeletonData / asset 等);深层递归不做,避免误清非 asset 的嵌套对象。
|
||||
*
|
||||
* 跳过结构字段(__type__/_parent/_prefab/_components/_children/node/__editorExtras__ 等)——
|
||||
* 这些走 disconnectSubtree / 父引用清理。
|
||||
*/
|
||||
function clearOrphanAssetRefs(element) {
|
||||
if (!element || typeof element !== 'object') return;
|
||||
for (const key of Object.keys(element)) {
|
||||
if (
|
||||
key.startsWith('__') ||
|
||||
key === 'node' ||
|
||||
key === '_parent' ||
|
||||
key === '_prefab' ||
|
||||
key === '_components' ||
|
||||
key === '_children'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const val = element[key];
|
||||
if (!val || typeof val !== 'object') continue;
|
||||
|
||||
// 单个 cc.Asset 引用 {__uuid__: string, __expectedType__: string}
|
||||
if (typeof val.__uuid__ === 'string' && typeof val.__expectedType__ === 'string') {
|
||||
element[key] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 全部由 cc.Asset 引用组成的数组(如 cc.Animation._clips)
|
||||
if (Array.isArray(val) && val.length > 0) {
|
||||
const allAssetRefs = val.every(
|
||||
(v) => v && typeof v === 'object' && typeof v.__uuid__ === 'string' && typeof v.__expectedType__ === 'string'
|
||||
);
|
||||
if (allAssetRefs) {
|
||||
element[key] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─── elements 重排:__id__ 引用映射 / 收缩 ───────────────────
|
||||
//
|
||||
// 用于 dedupe-component:合并删除组件后,所有 __id__ 指向被删/被合并对象的
|
||||
@@ -281,6 +332,7 @@ module.exports = {
|
||||
collectExistingFileIds,
|
||||
uniqueFileId,
|
||||
disconnectSubtree,
|
||||
clearOrphanAssetRefs,
|
||||
countPropertyRefs,
|
||||
isReservedCompField,
|
||||
filterCompRefsInElements,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
'use strict';
|
||||
|
||||
const { normalizeComponentType, isStub, resolveNode } = require('../helpers.js');
|
||||
const { cleanupRootTargetOverrides } = require('../id-utils.js');
|
||||
const { cleanupRootTargetOverrides, clearOrphanAssetRefs } = require('../id-utils.js');
|
||||
|
||||
function execRemoveComponent(prefabData, op) {
|
||||
const { elements, rootId } = prefabData;
|
||||
@@ -72,6 +72,12 @@ function execRemoveComponent(prefabData, op) {
|
||||
}
|
||||
cleanupRootTargetOverrides(elements, rootId, removedIds);
|
||||
|
||||
// 清孤儿组件里的 cc.Asset 引用字段(_spriteFrame / _defaultClip / _clips / _font 等)。
|
||||
// 不清会被 bundle build 扫整个 data 数组撞到、算入依赖图,运行时拉不存在的资源 404。
|
||||
for (const id of removedIds) {
|
||||
clearOrphanAssetRefs(elements[id]);
|
||||
}
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
'use strict';
|
||||
|
||||
const { isStub, resolveNode } = require('../helpers.js');
|
||||
const { disconnectSubtree, cleanupRootTargetOverrides, syncNestedRoots } = require('../id-utils.js');
|
||||
const {
|
||||
disconnectSubtree,
|
||||
clearOrphanAssetRefs,
|
||||
cleanupRootTargetOverrides,
|
||||
syncNestedRoots,
|
||||
} = require('../id-utils.js');
|
||||
|
||||
function execRemoveNode(prefabData, op) {
|
||||
const { elements, rootId } = prefabData;
|
||||
@@ -48,6 +53,12 @@ function execRemoveNode(prefabData, op) {
|
||||
|
||||
disconnectSubtree(elements, targetId);
|
||||
|
||||
// 清孤儿元素里的 cc.Asset 引用字段(asset / _spriteFrame / _defaultClip / _clips 等)。
|
||||
// 不清会被 bundle build 扫整个 data 数组撞到、算入依赖图,运行时拉不存在的资源 404。
|
||||
for (const id of subtreeIds) {
|
||||
clearOrphanAssetRefs(elements[id]);
|
||||
}
|
||||
|
||||
// 软删后同步外层 PrefabInfo.nestedPrefabInstanceRoots,清掉孤儿 stub 引用
|
||||
syncNestedRoots(elements, rootId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user