Skip to content

v0.6.4 — 生成链路修复 + 主线程队列背压

Choose a tag to compare

@High-cla High-cla released this 22 Sep 22:17

改动

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] 开头的行。