DreamFXLang
诊断码

DFX8xxx — 反编译器

DFX8xxx 段的全部诊断码,每条带严重级别、逐字消息、成因与修法。

本族共 14 条(10 错误 / 4 警告)。消息是编译器持有的格式串:%s%d%c 在运行时被替换掉。

DFX8000

错误抛出位置Decompiler/DreamFXDecompiler.cpp:2409

Cannot decompile a null system.

原因. 资产路径解析不到东西,或者解析到的不是一个 Niagara System。

修复. 检查路径。dfx decompile /Game/FX/NS_Spark 收的是包路径。

DFX8001

错误抛出位置Decompiler/DreamFXDecompiler.cpp:2605

Could not read emitters: %s

原因. 这个系统的 emitter 读不出来。

修复. 内层消息是 adapter 的。系统整个加载不了的话报的是 DFX8000。

DFX8002

警告抛出位置Decompiler/DreamFXDecompiler.cpp:2622

Skipping emitter '%s': %s

原因. 某一个 emitter 导不出来,系统的其余部分还是导出了。

修复. 那个 emitter 的导出是不完整的。dfx coverage 会在所有系统上一次性给出同样的信息。

DFX8003

错误抛出位置Decompiler/DreamFXDecompiler.cpp:2765

Cannot decompile a null emitter.

原因. Export .dfe 的入口被触发时什么都没选中,或者选中的资产加载失败。

修复. 右键单个 UNiagaraEmitter 资产。住在系统内部的 emitter 不是独立资产 —— 那种情况导出整个系统。

DFX8004

错误抛出位置Decompiler/DreamFXDecompiler.cpp:2777

Could not create a host system to read the emitter through: %s

原因. 读一个 emitter 需要一个拥有它的系统:外部编辑 API 的每个读取器都通过系统寻址。 /Temp/DreamFX 下那个一次性宿主没建起来。

修复. 内层消息是 adapter 的。/Temp 下的东西不落盘,所以这是一次内存内的失败 —— 通常是 Niagara 插件没初始化好,而不是这个 emitter 有什么问题。

DFX8005

错误抛出位置Decompiler/DreamFXDecompiler.cpp:2801

Could not copy emitter '%s' into a host system: %s

原因. emitter 拷不进宿主系统。Niagara 的 AddEmitter 把它作为模板拒绝了。

修复. 内层消息是 Niagara 的。最常见的原因是这个 emitter 资产是被老得多的引擎版本存的; 在 Niagara 编辑器里打开再存一次就会升级它。

DFX8006

错误抛出位置Decompiler/DreamFXDecompiler.cpp:2822

Could not read emitter '%s': %s

原因. emitter 拷进宿主了,但它的拓扑读不回来。

修复. 内层消息是 adapter 的。dfx coverage 会在所有系统上跑同一条读路径, 是判断「问题出在这个 emitter 还是读路径本身」最快的办法。

DFX8010

错误抛出位置UI/DreamFXAssetCommands.cpp:535

'%s' cannot be adopted: '%s' has no DreamFXLang form yet, so adopting would destroy it on the first rebuild. Export .dfs instead.

原因. Adopt 拒绝一个带有 DreamFXLang 表达不了的特性的资产。每一项特性报一行。

这道门是 adopt 之所以安全的原因。adopt 意味着文本成为这个资产唯一的真相来源, 所以带着已知缺口去 adopt,等于在第一次重建时把没活下来的东西销毁掉 —— 静默地,而且没有任何 diff 可看。

修复. 改用 Export .dfs。它写出同样的文本、不碰资产,并把缺口列在文件头里。 想知道自己内容里哪些桶是敞开的,跑 dfx.ps1 coverage

DFX8011

错误抛出位置UI/DreamFXAssetCommands.cpp:576

'%s' is already generated by an existing source, so a second one would silently overwrite it on alternate builds. Edit that file instead.

原因. 已经有另一个 .dfs 声明了同一个目标资产。两份源码生成一个资产会轮流互相覆盖,谁后建谁赢。

两边在构建期都发现不了这件事 —— 都会成功。唯一能拦住它的地方就是这里,在第二份存在之前。

修复. 去改那份已有的源码。它的路径在消息里,也在 toast 里。

DFX8012

错误抛出位置UI/DreamFXAssetCommands.cpp:659

'%s' was adopted, but re-exporting the rebuilt asset does not reproduce this file. First difference at %s

原因. 资产被 adopt 并重建了,但把重建后的资产再导出一次,得不到刚写下的那份文件。第一处差异的行号在消息里。

因为 DFX8010 已经排除掉了每一个已知缺口,所以这里的不匹配是生成器或反编译器的真缺陷,而不是预期内的丢失。

修复. 源文件留在磁盘上,资产也是照它重建的,所以文本无论如何都是权威的那一份 —— 什么都没丢。 把差异行报上来:往返不是一个不动点,正是 DreamFX.Corpus.RoundTrip 存在要防的事, 所以走到这里的案例是语料还没覆盖到的那一类。

DFX8013

错误抛出位置Generation/DreamFXGenerator.cpp:3332

This file sits in the decompiled output directory but Name=\"%s\" builds '%s', outside the '%s/' namespace. That would overwrite the asset it was exported from. Re-export it, or move the file out of the decompiled tree to keep this name.

原因. 这个文件住在 Decompiled Output Directory(默认 DFX/Decompiled)里, 但它的 Name= 解析出的资产在 Decompiled/ 内容命名空间之外。构建它会盖掉它当初被导出的那个资产 —— 而那通常是作者只打算读一读的第三方内容。

几乎每一次都是插件开始给导出「换家」之前写下的旧导出:那些文件命名的是原资产, 当时是靠把整棵反编译树排除在构建之外来兜底的。现在这棵树是普通源码,所以这项检查搬到了文件自己身上。

修复. 重新导出一次(右键 ▸ Export .dfs,或 dfx decompile-all -Path=...)。新文件命名 Decompiled/<原目录>/<资产>,在原件旁边重建一个镜像 —— 这正是它可以随便改、随便存的原因。

如果你的本意确实是让这段文本成为那个资产的真相来源,那件事叫 Adopt 而不是 Export: 把文件从反编译树里挪进某个 DFX/ 目录,名字保持不变。Adopt 写出来的正是这个安排, 并且在导出会丢掉语言还表达不了的东西时拒绝执行(DFX8010)。

DFX8014

警告抛出位置Decompiler/DreamFXDecompiler.cpp:1442

Emitter '%s' inherits from '%s'. The export flattens the inheritance: the merged stack is carried in full, but the rebuilt emitter no longer follows the parent, so later parent edits will change the original and not the mirror.

原因. 这个 emitter 继承自一个父 emitter 资产(资产上的 VersionedParent)。导出会把继承摊平 —— 而这件事丢什么、不丢什么,是在这条警告措辞之前量过的(2026-08-11,NS_Spawn_Teleport_RootNE_C/NE_C002):一个继承 emitter 自己的图就是那份完整的合并副本,所以导出携带了完整的有效栈, 重建出来的 emitter 行为与原件一致。摊平丢掉的是那条链接。镜像是一个独立 emitter; 对父资产的编辑会经 Niagara 的合并机制传进原件,并且静默地永远到不了镜像。

修复. 如果镜像只是一次迁移快照,那就什么都不用做 —— 分歧只在有人去改父资产时才开始。 父资产还在维护的话,要么在父资产改动后重新导出(合并后的栈会带上改动),要么继续在编辑器里维护原件。 将来的 from "<父资产>" inherit 形式能重建这条链接,设计有了但没有落地;这条警告就是它能买到什么的记录。

DFX8015

警告抛出位置Decompiler/DreamFXDecompiler.cpp:1490

Emitter '%s' carries %d event handler(s) this export cannot represent%s. The rebuilt emitter will receive no events -- an event-spawned emitter comes back permanently empty. The gap header names each handler's source emitter and event.

原因. 这个 emitter 带着导出没有文本形式的事件处理器。事件处理器本身是支持的 —— 它们导出成 OnEvent(...) 块 —— 所以现在只在两种更窄的情况下触发:

  • 这个 emitter 有不止一个处理器(每个 emitter 只有一个可表达,因为写入侧是通过单一的零 usage id 去够事件栈的);
  • 导出的是独立的 .dfe,那里没有兄弟 emitter 可以给处理器的 Source 命名 (存着的 SourceEmitterID 是一个任何重建都复现不了的 handle guid,所以来源是按 emitter 名字旅行的)。

修复. 多处理器的情况,把接收方 emitter 拆开,每个带一个处理器。独立导出的情况, 改成把整个系统导出成 .dfs,那里源 emitter 存在、可以被命名。两种情况下缺口头都会写明每个处理器的源 emitter 与事件, 所以没有东西是静默丢掉的。

DFX8016

警告抛出位置Decompiler/DreamFXDecompiler.cpp:1537

Emitter '%s' carries %d simulation stage(s) this export cannot represent (custom stage class or missing script). The gap header names each one.

原因. 这个 emitter 带着导出没有文本形式的 simulation stage。普通 stage 导出成 Stage name(...) 块, 不会触发这条;剩下的是那些类不是引擎 UNiagaraSimulationStageGeneric 的(自定义 C++ stage), 或者脚本对象在资产上缺失的。缺口头会逐个点名,于是这次丢失会一路留到 code review, 而不是只活在一份 commandlet 日志里。

修复. 源文件里没什么可修的 —— 这是表达能力的边界。如果这个 stage 很重要, 那就继续在 Niagara 编辑器里维护那个 emitter;重建出来的镜像不会跑它。

本页目录