v0.6.4 — 生成链路修复 + 主线程队列背压
改动
1. 生成链路回归云端行为(修「连上了却生成不了」)
v0.6.3 引入的本地自服务暴露出一个我自造的缺陷:我把 /api/mine 当成了生成的前置门禁,而 /api/mine 走主线程队列。/api/spawn 本身只在 HTTP 线程入队、由主线程稍后消费,两者无依赖关系 —— 这个门禁会挡掉本来可用的生成。
- 移除 4 处
if (!(await checkServer()))门禁,checkServer只探/api/health - 移除「生成中」中间态与
waitSpawned轮询;spawnItem不再置灰按钮或改文案 - 补上根因:
Application.runInBackground = true—— 游戏失焦时主线程不跑OnUpdate,队列永不消费,表现为「连上了却生成不了」
2. 连续生成
- 生成按钮保持可点,不再禁用、不再改文字,可连续点击十个
3. 逐件独立生成(不在物品格上显示数字)
SpawnItem 原先用 SetAmount 设数量,物品格上会显示数字。改为循环 count 次创建互相独立的物品(不堆叠):
for (int i = 0; i < count; i++) {
if (!TryCreateSpawnItem(id, out GameItem item)) break;
if (!TryAcceptIntoMainInventory((GameInventory)inv, item, id)) break;
if (first == null) first = item;
done++;
}部分成功时按实际 done 记录,不谎报数量。
4. 代码质量:消除重复键表
ResolveNamedTableId 原用两个 switch 各写 11 条 arm,把同一份「键集合」知识存了两处,加表必须同步改两个 switch。收敛为单个 Dictionary<string, Func<string>>,净 −18 行。
补 null 守卫:Dictionary.TryGetValue(null) 抛 ArgumentNullException,而旧 switch 对 null 走 default 返回 "" —— 这是失败模式改变而非等价重构,故显式 if (tableKey == null) return "";。差分测试 180 组 / 0 差异(覆盖 null、未知键、空值、const 抛异常四类边界)。
5. 主线程作业队列加背压(唯一够格称性能问题的项)
OnUpdate 的 while (PendingJobs.TryDequeue(...)) 无单帧上限 —— 积压时一帧跑完整队列导致卡帧。改为队列 ≥ 32 时立即拒绝:RunOnMainThread 增 overloaded 出参,过载回 503,与超时(500/500/400)区分。前端无需改动(apiFetch 已把 ok:false 渲染成 toast)。
用 PendingJobs.Count 而非自维护计数器,避免「忘记递减 ⇒ 永久 503」的泄漏面;过载分支在 new MainThreadJob 之前 return,不会走到 finally 去 Dispose 尚未存在的句柄。
顺带收窄 PlaceInto 参数:cachedRects/selfSupport 带默认值却排在 out 之后,改必填、out 归末,3 个调用点同步。
验证
- 三个 csproj
dotnet build -c Release均 0 警告 0 错误 - 内嵌网页资源与
docs/源文件逐字节比对 3/3 IDENTICAL(132349 / 232520 / 14365 B) - 已删的
.dot.warn与.nav-item .swatch确认不存在于 DLL 内 - 差分测试证明 tableKey 重构等价(180 组 / 0 差异)
- 静态检查:三只读路由全部接线、503 分支 3 处、
timeoutMs默认参数残留 0、/api/health不走队列
资产
| 文件 | 说明 |
|---|---|
| ProgressMod.dll | 452096 B — 含内嵌网页;生成链路修复主体 |
| InventorySorter.dll | 57856 B — 参数收窄 |
| NetworkUnlockMod.dll | 8704 B |
未做
- 真机验证:无运行时实测数据。背压阈值
32为估算值(依据是单帧处理 32 个纯读作业远低于 5s 超时窗口),未经实测。 PendingSpawns/PendingItemOps是同形状的无界队列,故意未加上限 —— 它们是写队列,过载时拒绝会让「连续生成」的点击静默丢失(前端已弹「已生成」而实际没生成),比卡帧更糟。Core.cs的长方法与循环内Contains仅报告,未改动。
日志看 [Spawn] 开头的行。