DSP MolecularHub
分子装配枢纽把八道工序折叠进一台建筑:八个配方槽共用一条分子级内部总线,任一槽的产物都被其它槽直接取用,不占一条传送带,八个槽并行运行,相当于把八台制造台装进一台机器。复用制造台 Mk.IV 的模型并染成青金色,宇宙矩阵阶段解锁;支持 Shift 复制/粘贴建筑设置与蓝图整厂迁移。适配 DSP 0.10.35 / BepInEx 5.4 / CommonAPI 1.6.7。Changelog
0.1.9-release — 2026-10-28
发布定稿:关闭全部调试钩子(构建指纹 v0.1.9-release,版本号仍是 0.1.9)。
- 不再读取插件目录下的
selftest.txt,不再自动开窗;诊断采样(DiagProbe)只在 hot-tunedebug=1时运行。 CompatProbe(停用 CommonAPI 1.6.7 在 0.10.35 上必崩的ProtoSet<T>.Select后缀)属于兼容修复,发布版保留。- 行为与此前 r7 完全一致:存档 trailer(
MHUBTRL1)倒序扫描、插件目录不生成任何文件、复制粘贴全链路。 - 调试开关(可选,按需创建
<插件目录>\hot-tune.txt):debug=1打开日志;copypaste=0关闭复制粘贴补丁;insertfix=0关闭分拣器投料短路。
0.1.9-r7 — 2026-10-27
存档尾块读取兼容其它 MOD(构建指纹 v0.1.9-r7,版本号仍是 0.1.9)。别的 MOD(如品质系统 QSystem)也会往同一个 .dsv 末尾追加自己的尾块;如果它在我们的 MHUBTRL1 之后写入,我们的帧就不再位于文件最后 12 字节,旧读法会静默丢掉 8 槽配方与总线存货。现在读档改为文件尾 4MB 内倒序扫描本 MOD 魔数,并对「长度字段自洽 + JSON 可解析」双重校验,取最靠后(最新)的一个自洽帧;窗口内找不到才当作旧存档。写入逻辑不变(仍是追加 + 改写头部文件长度 + 自校验失败回滚)。独立测试 11/11(含「我们的帧 + 外来帧 + 垃圾字节」「重复追加取最新」「长度字段不自洽拒绝」等)。
顺带审计(同类越界问题):本 MOD 源码没有 entityId + 1 这类算术,所有拿游戏 id 索引 entityPool / entitySignPool / assemblerPool 的位置都有 id <= 0 || id >= pool.Length 护栏,因此不存在哨兵值溢出导致的数组越界。
0.1.9-r6 — 2026-10-27
插件目录不再生成任何额外文件(构建指纹 v0.1.9-r6,版本号仍是 0.1.9)。r5 让配置跟着存档走后,插件目录的 save\molecularhub.json 仍被双写作为降级兜底;按用户要求已彻底移除——现在只往 .dsv 末尾写附加段,插件目录不会再多出 save 文件夹或任何文件。以前生成的 save\molecularhub.json 可以直接删除,不影响任何存档数据。注意:本版起旧 DLL(r5 及以前)不再有新写入的 JSON 可用,降级前请确认。
0.1.9-r5 — 2026-10-27
枢纽配置跟着存档文件走(构建指纹 v0.1.9-r5,版本号仍是 0.1.9)。之前 8 槽配方与内部总线存货存在插件目录的 save\molecularhub.json,只把 .dsv 存档拷到别的机器/存档目录时会失效;现在改为写进存档文件本身:
- 游戏存档完成后,在
.dsv末尾追加一段隐蔽数据[json][长度]["MHUBTRL1"],并把文件头记录的总长度改成新长度——原版读档校验通过,不装本 mod 也能正常读/存。 - 读档时解析这段数据,按「星系种子 + 星球 index」把每颗星球的 8 槽配方与总线存货套回,所以拷贝存档 = 带走配置。
- 不完整/损坏的存档不会被追加;写入失败会自动回滚,存档文件不受影响。
- 存档是唯一持久化位置:配置不再在插件目录留任何文件(旧版曾写
save\molecularhub.json,自 0.1.9-r6 起已移除)。
0.1.9-r4b — 2026-10-27
补原版属性表(DescFields)。上一版描述/文案已换新,但原版建筑 tooltip 的数值行来自 ItemProto.DescFields,CommonAPI 注册的物品默认不带这张表,所以只显示描述与「制造于 / 手动制造」,看起来"没改成制造台格式"。现在补上 DescFields = [23,22,11,12]:耐久度 / 制造速度 / 工作功率 / 待机功率,顺序与原版制造台一致;「制造速度」显示 1x8(GetPropValue postfix 只改显示,且按 DescFields[index] 判定,不会误伤功率行)。构建指纹 v0.1.9-r4b,版本号仍是 0.1.9。
0.1.9-r4 — 2026-10-26
文案 / 本地化 / 发布格式轮(上一轮 5 条实机问题全部通过后的收尾)。版本号仍是 0.1.9,构建指纹 v0.1.9-r4。
- 建筑 / 物品描述改成原版制造台格式:先用一两句话讲清「这台机器解决什么问题」,具体数值(耐久、功率、速度)交给自动属性表,不再在描述里重复。
- 「制造速度」显示为
1x8:八槽并行,但生产数值仍是每槽 1×(assemblerSpeed=10000不动);通过ItemProto.GetPropValue的 postfix 只改提示显示。 - 物品描述重写为分子装配视角:「八道工序折叠进一台建筑 + 分子级内部总线直连」。
- 科技描述 / 结论改成科技风味的原理说明:分子筛拆解原料、分子轨道在八个装配腔之间搬运与键合,通道本身是分子级所以不需要传送带。
- 补齐英文并按语言回退:全部文案都有中文 / English 两套;CommonAPI 只支持 en(1033)/cn(2052)/fr(1036) 三个语言桶,其它语言原本会显示空白 —— 现在在翻译出口统一兜底:中文环境显示中文,其它任何语言显示英文。
- 打包按 r2modman / Thunderstore 格式:
manifest.json描述重写(更生动、讲清玩法),整个清单 511 字符,远低于 2556 字符的检测上限;zip 结构与 0.1.8 一致(根manifest.json/README.md/CHANGELOG.md/icon.png+BepInEx/plugins/DSP-MolecularHub/)。 - 开发文档同步更新,清理过期状态描述。
0.1.9-r3 — 2026-10-21
第二轮实机反馈修复(拆除继承 / 蓝图第 3 台 / 分拣器误标 / 空地粘贴提示 / 筛选条选择)。版本号仍是 0.1.9,构建指纹 v0.1.9-copypaste-r3。
- 修「鼠标指空地按
>也弹『已粘贴』」:根因不是粘贴补丁误判,而是原版查看焦点没清——点枢纽打开自绘窗口时我们抑制了原版制造台窗口,绕过了原版UIAssemblerWindow._OnClose里的InspectNothing(),于是inspectId一直停在上次点过的枢纽上;原版</>在光标下没有实体时会回退到 inspectId,空地按>实际粘到了那台枢纽(真的写入并弹提示)。修复:HubWindow.Close()带守卫调用InspectNothing();另外枢纽幽灵(未落地)的粘贴保持静默,不写内容也不弹提示。 - 修「拆掉设过配方的枢纽后,新枢纽继承旧配方和材料(拆 3 个继承 3 个)」:四条根因叠加——①原版拆除只回收
entityPool[id].assemblerId指向的那 1 个组件,枢纽有 9 个;②r2 之前拆除补丁签名写错(int __1= bool),清理逻辑从未执行;③实体 id 会被 LIFO 回收复用,新枢纽Init的ReuseExistingSlots把旧组件(带 recipe/served/produced)无条件收编;④JSON 存档按 entityId 合并且从不剔除已拆记录。修复:拆除补丁签名改int __0;OnRemoved退物品后删 8 槽 + 接口组件并清assemblerId;新建筑落地前CleanupStaleForNewEntity清掉同 id 的残留组件(先退款再删);ForgetSavedEntity在拆除/新建时同步删 JSON 旧记录;读档初始化前CleanupDanglingComponents清挂错实体的组件。 - 修「蓝图 / Shift 复制到第 3 台起分拣器不抓料、且继承上一台部分产物」:与上一条同源(id 复用 + 旧组件被收编)。落地前清理切断收编后,新枢纽只用自己的新组件。已建坏的枢纽不会再自我扩散;修复后重新放的建筑是干净的。
- 修「分拣器出现枢纽配方图标、点它打开独立枢纽界面」:实体 id 被回收后,注册表里的旧
HubComponent仍在每 tick 驱动那台分拣器(DriveHubs/BindEntityNeedsAll/标志压制都没有「实体是否还是枢纽」校验,RefreshHubSign直接写signs[entityId])。修复:新增HubComponent.IsAlive()(实体在、proto 仍是枢纽)+HubRegistry.DropQuiet()软摘除;DriveHubs(倒序遍历)、BindEntityNeedsAll、ForceHubSignStableCore、RefreshHubSign全部加实体校验。 - 修「分拣器产物筛选条可以出现但不能选择(左右移动后立刻弹回第一个空白项)」:原版
SetOutputEntity在目标实体没变时早退、刻意不动selectedIndex;我们的 postfix 每次都会执行,并用tryFindFilter(每帧被buildPreview.filterId重置成 0)重算选中项 → 选择被打回 0。修复:postfix 保留实例上已有的selectedFilter/selectedIndex,列表未变化时直接返回,不再覆盖玩家的选择。 - 出问题时
hot-tune.txt写copypaste=0并重启,可整组关闭复制/粘贴补丁(分拣器筛选 UI 无开关、始终可用)。
0.1.9-r2 — 2026-10-21
实机反馈修复轮(复制/粘贴 + 套用语义 + 分拣器投料)。版本号仍是 0.1.9,构建指纹 v0.1.9-copypaste-r2。
- 修复「复制非枢纽建筑也提示已复制枢纽配方 / 粘到枢纽时误套上一次的配方」:原版
BuildingParameters.SetEmpty()并不会清content,上一次复制留下的载荷会一直残留。现在在SetEmpty的 postfix 统一清洗本 MOD 载荷(P7), 复制出口(P1)复制到非枢纽时也主动清陈旧载荷;提示文案改为按"最近一次复制/粘贴是否真的命中枢纽"决定。 - 修复「粘贴不按类型」:目标是普通建筑(或枢纽幽灵)而剪贴板里是枢纽载荷时,直接不执行粘贴(静默、不弹提示), 不再退化成原版"改它那一条配方";只有剪贴板里没有枢纽载荷时,普通建筑才走原版逻辑。
- 修复「从背包/快捷栏拿出的枢纽自带配方」:关闭建造工具(P6)以及任何
SetEmpty都会清掉建造模板里的载荷。 - 修复「槽里有物品时换/清配方、拆建筑不返还物品」:
SetSlotRecipe换配方前先TakeBackItems_Assembler退还该槽全部缓存(产物/半成品/原料);拆除枢纽时 8 槽 + 接口逐槽退还,全部走原版左下角物品提示(UIItemup.Up)。 - 界面取料反馈改为原版样式:左键原料行/产物行取料不再弹一行小字,改为原版左下角物品浮动提示;清空槽位也不再弹文字。
- 修复「蓝图复制多台枢纽后只有前两台能被分拣器投料」:根因是 9 个装配组件共用同一个
entityPool[hub].assemblerId, 接口位解析会误把槽位当接口、接口位 id 不是最大时entityNeeds每帧被原版抢走、原版装配体窗口的抑制逻辑用全局静态 保存/恢复assemblerId会把它写成 0。修复:InterfaceSlotId()排除 8 槽并回填assemblerId;EnsureSlot分配失败即报错且无条件回填接口位;Init改为「先复用读档槽位 → 分配 8 槽 → 最后建接口位」(接口 id 必为最大);InsertFix门禁改用自愈解析,assemblerId<=0时不再放行原版(原版必然吞料);装配体窗口抑制改为按 entityId 的字典; 孤儿组件清理不再误删"挂在枢纽实体上的组件"。已建坏的枢纽会在下次载入 / 下次分拣器 tick 的自愈路径里被修正, 不必拆掉重造。 - 新增:分拣器建造预览的「快速筛选」UI:给枢纽放分拣器、分拣器指向枢纽后,会出现原版多产物配方那样的产物图标条, 可直接点选要输出哪一条槽位产物(纯 UI,不影响存档与生产;与原版多产物配方共用同一控件,6 个图标上限)。
- 出问题时
hot-tune.txt写copypaste=0并重启,可整组关闭复制/粘贴补丁(分拣器筛选 UI 无开关、始终可用)。
0.1.9 — 2026-10-19
配方复制 / 粘贴(A 方案:走原版 BuildingParameters.content 载荷通道)。
- 三条链路一次打通,全部不依赖 CommonAPI 的
ICopyPasteSettings(那套在 0.10.35 已失效):Shift复制建筑 → 幽灵 → 落地:BuildingParameters.CopyFromFactoryObjectpostfix 写载荷 →ApplyPrebuildParametersToEntityprefix 暂存 →AddEntityDataWithComponentspostfix 套用。</>(原版复制/粘贴建筑设置):PasteToFactoryObjectprefix 直接套用到已有枢纽。- 蓝图:载荷随
BlueprintBuilding.content存档/读档,旧蓝图(无载荷)行为不变。
- 载荷格式
MHUB1:r0,r1,...,r7(纯 ASCII,刻意避开 marker 分隔符\n);解码失败 (null / 无 magic / 字段数不对 / 数字越界)一律放行原版,普通制造台/仓储/分拣器的复制粘贴行为完全不变。 - 防丢物品:套用前逐槽
TakeBackItems_Assembler把槽内缓存物品退还玩家背包,再SetSlotRecipe(SetSlotRecipe会清 served/produced/incServed,不退就等于吞物品)。 - 解锁校验:未解锁的配方跳过该槽(粘贴不能绕过科技进度)。
- 精确覆盖:目标槽位多余的配方清 0(新增
HubComponent.ApplyRecipesExact;读档用的ImportRecipes语义不变)。 - 空枢纽不写载荷:避免“复制一个空枢纽 → 粘贴”把目标 8 槽全清空。
- 提示文案:复制/粘贴成功时显示「已复制 / 已粘贴分子装配枢纽的 8 条槽位配方」(en/zh/fr 已注册)。
- 清理:删除
HubComponent里 CommonAPIICopyPasteSettings的 4 个空壳方法(该接口在本版本不会被调用,留着误导)。 - hot-tune 新键
copypaste(默认 1):0= 本次会话不安装复制/粘贴补丁。启动期读一次,改了要重启游戏。 - 补丁隔离:
HubCopyPaste不使用[HarmonyPatch]特性(避免被Plugin.Awake的 assembly 级PatchAll扫到), 改为AccessTools.Method+ 逐点harmony.Patch,每个 patch 独立 try/catch —— 任一目标方法签名漂移只让 那一条链路降级为原版行为,不会导致整个 MOD 加载失败。 - 不新增常态日志行:安装结果/细节全部走
debug=1。
0.1.8 — 2026-10-18
对外发布版:默认静默日志(修刷屏)。
- 人类反馈发布版持续输出日志(OrbitalRing profile 一次会话 657 行,其中
[sign]434 行)。 - 新增统一日志闸门
HubLog(LogGate.cs):全部Plugin.Log.LogX(...)经它过滤。- 默认(hot-tune
debug=0):只输出 加载 2 行 + hot-tune 1 行 + 真正的 Warning/Error(合计硬上限 ≤5 行/会话); debug=1:恢复全部调试/探针/UI 交互日志([sign]额外 cap 20)。
- 默认(hot-tune
- 已门控:
[sign]、生产/缓冲/守恒/接口位探针、TransferToSlots入口、生产循环、[needs]/[R1]、[probe-*]、[visual]、[insertfix]、[F1]/[cleanup]、配方等级对齐/各制造台类型、超限提示、UI 交互(SetSlotRecipe/ 打开配方选择器/回读/打开窗口/挂事件)、收料/收产物成功日志。 [loss]守恒异常保留 Warning(计入 2 条预算),明细仅debug=1。
0.1.7 — 2026-10-18
产物消失修复 + 科技位置微调。
- 修复产物定期凭空减少:
HubComponent.RebuildInterfaceRecipe每次接口映射变化都重建produced = new int[...](清零),但快照slotLastProduced[]未清零;下一 tick 的 “分拣器取走量 = slotLastProduced - produced”把清零误判为取走,ConsumeFromStock随即从 真实库存(槽位 produced + 内部总线)扣掉对应数量 → 产物定时消失(与是否有出库分拣器无关)。 修复:形状/产物顺序不变时复用原数组;换数组时同步清零slotLastProduced;ConsumeFromStock先按真实可用量夹紧,异常时打[loss] ConsumeFromStock …;输出快照处对不上也打[loss]。 - 科技位置按人类要求改为 (72,-4)(前置引力矩阵 1705(68,0),|ΔY|=4 < 10 仍满足
UITechNode.UpdateConnDynamic画线条件;该格已核实空闲)。 - 其余与 0.1.6 一致(insertfix、科技 1993、GridIndex=2114、BuildIndex=810、tooltip 名称等)。
0.1.6 — 2026-10-18
日志/诊断打磨(功能不变)。
- insertfix 开启时,输入种类超过 6 的告警从 Warning 改为 Info,并注明“已由 insertfix 接管,分拣器仍可直接送入内部总线”, 不再误导为“送不进来”。
- 修正调试探针
needsLinkedToEntityNeeds误报:insertfix 会把entityNeeds[枢纽实体]指向 8 槽去重清单 (sorterNeeds),探针同时接受该引用,不再刷[R1] 接口位 needs/requires 断言失败错误。 - 其余行为与 0.1.5 完全一致(insertfix=1、1× 速度、科技 (72,0)+前置 1705、GridIndex=2114、BuildIndex=810)。
0.1.5 — 2026-10-18
分拣器投料修复(重点)。
- 根因(反编译实锤):原版
FactorySystem.GameTick的装配体循环按 assemblerPool 顺序写entityNeeds[entityId] = 组件.needs(Assembly-CSharp.full.cs:99082/99105)。枢纽实体有 1 个接口位 + 8 个槽位组件共用 entityId,最后处理的是槽位组件(needs 通常全 0); 分拣器 careNeeds 读entityNeeds[insertTarget](InserterComponent.InternalUpdate:54252)→ 指向枢纽的分拣器永远不抓料。原版InsertInto对装配体还硬编码只匹配requires[0..5](:217108-217177), 星环(POR) 亦 patch 了InserterComponent.InternalUpdate_*。 - 修复:Harmony Prefix(
Priority.First)FactorySystem.GameTickInserters:插入器并行派发前把所有枢纽entityNeeds[实体]重绑到 「8 槽全部 requires 去重清单」(前 6 个保持原申报顺序);PlanetFactory.InsertInto:目标是枢纽接口实体且物品属于该清单时,直接写内部总线并return false短路原版/POR;busCap满返回 0;remainInc/__result语义保持原版。
- 线程安全:总线读写加
busLock(并行插入器线程 vs 主线程 TransferToSlots)。 - hot-tune 新增
insertfix=0/1(默认 1;兼容旧键stackfix),0 = 完全回退 A/B。 - 同时包含 0.1.4 的显示修复(科技 (72,0)+前置 1705、配方 tooltip 名称)。
0.1.4 — 2026-10-18
两处显示修复。
- 科技树:位置改为
(72,0),可见前置改为 引力矩阵 1705。根因是UITechNode.UpdateConnDynamic只在「前置节点与本节点 Y 差 <10」时绘制依赖连线(Assembly-CSharp.full.cs:460692), 原 (80,4) 与 1508(80,0) 跨行只剩斜箭头;1705(68,0) 正右相邻可画完整引导线。 另外 1508 在星环 profile 里被改名为「T任务完成」,不再适合作为常规前置。成本仍为 2000 宇宙矩阵。 - 配方名:CommonAPI
RegisterRecipe短重载会自动拼产物名+"Recipe"作为 key, tooltip 显示成molecularHubNameRecipe;改为显式传 namemolecularHubName,并补注册兜底 key。
0.1.3 — 2026-10-17
科技节点可见性 + 高阶配方等级修复(兼容星环 OrbitalRing)。
- 科技 ID
4801 → 1993:根因是TechProto.page在ID>=2000时返回 1(升级科技页),UITechTree按 page 把节点分别实例化到graphGroup0/graphGroup1;原 4801 的节点在升级页, 主科技页只显示 1508→(80,4) 的依赖箭头。改回 <2000 后节点回到主科技页 (80,4)(1508 正上方)。 - 配方等级对齐黑台(制造台 Mk.IV):星环用
prefabDesc.assemblerRecipeType给不同机器分级 (Mk.IV 模型 456 → 12 物质重组),并把高阶配方重新归到这些类型;枢纽克隆 Mk.IV 的 PrefabDesc 早于星环覆写, 类型停在 4(Assemble)→ 只看到最低阶配方。现在在ProtoRegistry.onLoadingFinished与读档后 回读 Mk.IV 运行期类型并写入枢纽模型/物品 PrefabDesc;枢纽自己的配方选择器改为不按类型过滤(显示全部已解锁配方)。 生产速度不变:仍为 1×(slotSpeed=10000、drive=vanilla)。 - ⚠️ 科技 ID 变更:旧存档里该科技需要重新研究(物品/建筑/配方不受影响)。
0.1.2 — 2026-10-17
显示位置调整(按玩家反馈)。
- 科技树:科技位置改为
TechPosition = (80, 4)(原 (73,1))。 - 物品/配方选择器:网格位置改为
GridIndex = 2114(14×8 网格的 tab2 第一行第 14 列,右上角;原 2608)。 依据:UIItemPicker/UIRecipePicker的网格为 14 列×8 行(Assembly-CSharp.full.cs:427358/435390), GridIndex 解码为tab=idx/1000, row=(idx%1000)/100-1, col=idx%100-1。 - 建造菜单:
BuildIndex = 810(category 8 / child 10,即第 8 页第 10 个位置;原 404)。 依据:UIBuildMenu.StaticLoad用protos[BuildIndex/100, BuildIndex%100](数组ItemProto[16,13])。
0.1.1 — 2026-10-17
兼容性修复:科技 ID 从 1999 迁到 4801。
- 背景:同时安装「深空来敌 / DSP_Battle」时,对方也注册了科技 1999(玻色子操控),
CommonAPI 在 LDBTool PreAdd 阶段对重复科技 ID 抛
ArgumentException,游戏启动即崩溃。 - 本版把解锁科技改为 4801(避开原版 ≤1992、更多巨构 1918、深空来敌 1997-1999/6601-6608、星环 2108/3151-3153/5406-5407)。
- 物品 6007 / 模型 666 / 配方 163 不变,老存档的建筑/物品/配方不受影响。
- ⚠️ 已解锁 1999 号科技的旧存档需要重新研究 4801 号科技(科技解锁状态按科技 ID 保存,不会自动迁移)。
0.1.0 — 2026-10-17
首个公开发布版本。
新增
- 「分子装配枢纽」建筑:8 个独立配方槽(制造/化工/精炼/冶炼),槽间内部总线直连,产物自动喂给下游槽。
- 自制界面:8 槽网格(左键选配方、右键打开原版制造台、右上角 X 清空、可拖动);原料行/产物行各 8 格; 左键原料/产物收入背包(背包满自动退回总线);每槽 /min 产量。
- 缓存/速度热调:
hot-tune.txt在线生效(BepInEx 插件目录),含holdMul/holdFloor/productCap/requestMul/requestFloor/slotSpeed/drive等键。 - 旧存档自动清理:读档时清理历史遗留的“孤儿装配组件”(实体不认领的组件),修复标志闪烁与统计显示。
修复
- 指向枢纽的分拣器标志每帧 4↔6 闪烁(根因:8 个 entityId 指向分拣器的孤儿装配组件被原版 GameTick 循环写 sign)。
- 生产统计“设施”分组出现分拣器图标(同一批孤儿的
entityId被统计当成分组原型)。 - 9 个同实体装配组件的 anim/sign/needs 互相覆盖:渲染前归一,动画不再 8~9 倍速、枢纽标志稳定。
- 换配方后旧料残留导致“重设配方不生效”:清缓冲 + 外部(原版窗口)改配方也会兜底清理。
- 缓存无限增长:修正 needs 申报的 keep-mapped 自持逻辑,单物品原料总缓存回落到 ≈50。
其他
- 明确 1× 语义:
drive=vanilla单写入者,速度等价原版制造台(slotSpeed=10000)。 - 明确并 UI 提示原版“最多 6 种外部输入”的硬限制。
