fix(diag): 消除静默降级 —— 让地图与怪物生成的数据缺失响亮失败 #58
Labels
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: troytt/diablo2-web#58
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
背景
对
main分支(origin/main=4c2e399)的地图与怪物生成逻辑做了一次全量 hardcode / fallback 审计,覆盖约 15,000 行代码。完整报告见本 Issue 系列的父任务。审计发现的最严重系统性问题不是任何单点 bug,而是贯穿三层的「静默降级」(silent degradation)设计:数据缺失时不报错、不中断,而是替换成合成值继续生成。
结果是:一个数据完全损坏的世界仍然能「成功」生成,并通过全部 885 个测试。
本 Issue 追踪「让失败变响亮」这一优先级最高的修复方向。
1.
UNIMPLEMENTED_PASSES谎报「零缺口」src/game/maze.ts:852-856但同一文件
src/game/maze.ts:594-598自相矛盾地写着:打包脚本
scripts/pack-act-assets.ts:733-740亦证实:后果:
stats.unimplementedPasses在每一关都无条件报告[],设计好的预警通道彻底失效。修复方向:从「
specials为空的 level type 集合」+stats.unresolvedRoles/stats.notes重新填充该数组。2.
maze-objects.ts:238地板检测是死代码末尾的
|| true让整个prop1 / style / sequence内容检测恒为真。后果:物件会生成在没有真实地板美术的格子上。
修复方向:删掉
|| true,并补一个回归测试断言「空内容地板格不被判定为 openFloor」。3. 怪物美术三重吞异常 → 全场红色方块
三层嵌套
catch把「整个美术系统崩溃」变成「场景就绪,怪物是红的」,仅有一句console.warn。涉及位置:
src/scene/act-scene.ts:1250-1253——catch包住整个loadMonsterArtMap,返回空 Map,全场怪物变红方块src/scene/act-scene.ts:1231-1233—— 逐 speccatch,该类怪物全变红方块src/scene/act-scene.ts:1969-1991—— 红方块绘制点src/game/monster-art.ts:155-160—— 逐 COF 层catch,静默丢层,怪物缺肢体渲染修复方向:
ActSceneState中新增missingMonsterArt: string[]/monsterArtErrors: number并在 HUD 显示。console.error并计数。4.
MonLvl缺行时怪物强度暴涨约 20 倍src/game/monsters.ts:485-494缩放公式是
原始表值 × scale ÷ 100。回退到UNSCALED意味着直接使用原始表值:一只堕落者会拿到 21-61 HP 而非约 3 HP。看起来像平衡 bug,实为数据 bug。
修复方向:
monsterScaleFor在缺行时console.warn或直接 throw,而非静默返回UNSCALED。5. 数据失败 → 12 只假怪物冒充真内容
src/scene/act-scene.ts:1578-1592DEMO_MONSTERS是src/game/demo-data.ts:6-10手写的 3 只假怪(demo-fallenhp 12 dmg 3 cd 24 reach 36…)。更糟的是「是否城镇」的判断(
act-scene.ts:734/:953)是对英文显示名做includes('town')子串匹配 —— 中文或改名后的城镇关卡会在城里刷出 12 只假怪。且
demo-*id 不在MONSTER_ART_MAP中,所以它们同时也是红方块。修复方向:删除整条
DEMO_MONSTERS/PLACEHOLDER_MONSTER_COUNT = 12路径;规划失败时留空并上报。6. 伪造的遥测数据(让验证脚本报告虚假健康状态)
src/game/maze.ts:856unimplementedPasses恒为[](同第 1 条)src/game/wilderness-jungles.ts:611-616junglePathCells: 100(字面常量);riverBridges: Math.max(2, bridges.length)(无论实际如何至少报 2)src/game/wilderness-acts.ts:768-777plateauCells计数src/game/wilderness.ts:5049subTheme: 0src/game/wilderness.ts:2443-2454BordType 0的「整关仅一个」上限因min(1, Infinity)恒等于 1,实际是「每行一个」,预算从未起约束作用修复方向:所有
stats字段必须反映真实计数;伪造值一律改为实测值或显式null。验收标准
UNIMPLEMENTED_PASSES反映真实缺口,并有测试断言其非空(当specials为空的 level type 仍存在时)maze-objects.ts:238的|| true删除,附回归测试ActSceneState/ HUD 中观测到,附测试monsterScaleFor缺行时告警,附测试DEMO_MONSTERS路径删除npm run typecheck零错误,npx vitest run全绿TAG=agy
CONV=2a1934de-30ef-464e-b3f3-fcbcdbbc49f1
父追踪 Issue:#64(完整审计报告与修复路线图)
主控独立复验记录
已在
9d568ad(Merge branch 'fix/issue-58')合并到 main 并推送。主控在合并前(分支上)与合并后(main 上)各独立跑了一次完整验证,不依赖子进程自报:
npm run typechecknpx vitest runnpm run verify:generators净增 3 个测试文件、31 个用例。
两处实现取舍(已认可)
plateauCells: 0并在stats.notes点名「未实现」。理由:按 4 格步长在整图点单格只会画出一片麻点,那是把假数据换成假地形。真正实现该 pass 应另开 feature。junglePathCells语义明确化 —— 定义为「clearing/head/tail 宏格内实际画出的可走地面格数」,并新增「地面 + 水面之和必须等于画布实测」这条更强约束,而非放宽断言。值得记录的实现亮点
UNIMPLEMENTED_PASSES没有被换成另一张手写列表,而是改为从MAZE_LEVEL_TYPE_PROFILES推导(无 profile 行 /specials为空且无singleRoom),因此它无法再次与它所描述的表脱节。同时generateMaze改为按关卡类型上报unimplementedPassesFor(levelTypeName),而不是把全局并集当成单关的缺口。衍生发现(已分流到其他 Issue)
fallbackwarp → #60verify:generators的 19 条失败是生成器本体缺陷(Act 1 Wilderness 2/4/6 仅 62.5% 可达面积;Kurast 4 有 16% 贴图引用缺失)→ #60src/scene/net-scene.ts:172/374有另一套本地DEMO_MONSTERS兜底(从解析表构造,非手写假怪)→ 待评估src/game/monster-art.ts中部约 293 行有夹在类型定义之间的import,结构异味 → #63