[Parity][motion-input][S1][R] 本地寻路算法是自创的,和 1.13c 玩家路径(PATHTYPE_STRAIGHT)不同,导致预测路径与服务器分歧 #588

Closed
opened 2026-10-02 11:42:43 +00:00 by troytt · 0 comments
Owner

1.13c 客户端保真度审计立项(基准快照:7bd1090 / main @ 77a20c7)

证据标记说明:V-data = 1.13c MPQ 数据表 (.txt / animdata.d2 / .tbl / pal.pl2);V-src = D2MOO 逆向源码;V-bin = 1.13c DLL 反汇编;K = 1.13c 公认行为。

来源审计项:motion-input#8 — [S1][R] 8. 本地寻路算法是自创的,和 1.13c 玩家路径(PATHTYPE_STRAIGHT)不同,导致预测路径与服务器分歧

  • 位置:src/client/motion/pathfind.ts:1-16(设计说明)、:59-73(8 方向 + octile 启发)、:168-218(findNearestWalkableLocal)、:220-244(拉绳平滑)、:306-461(findPathLocal::314 maxExpanded 16384、:316 nearestRadius 10、:317 allowPartial、:325 连起点也做"最近可走"修正、:357 直视捷径、:438 部分路径)
  • 代码:const maxExpanded = options.maxExpandedNodes ?? 16384;const resolvedStart = findNearestWalkableLocal(grid, startX, startY, nearestRadius)
  • 原版:
    • 玩家的 DynamicPath 初始化为 PATHTYPE_STRAIGHT,nDistMax 73,nIDAStarInitFScore 70,nMoveTestCollisionMask = COLLIDE_MASK_PLAYER_PATH(V-src D2Common Path.cpp:719-726;路径函数表见 Path.cpp:104-123)。
    • PATH_Straight_Compute(D2MOO 注释标为 1.13c D2Common 0x6FDB7AD0)先用 PATH_Toward 直线前进;只有受阻且起点到终点的距离平方 ≤ 18²(=324)时,才调用 PATH_AStar_ComputePath 绕行,否则保留直线结果(V-src PathMisc.cpp:583-620)。
    • 路径点上限 MAXPATHLEN 78(AStar.cpp:436、IDAStar.cpp:369)。|Δ|>100 直接拒绝(Path.cpp:394-397)。目标被挡时用 PATH_FindValidTargetCoordsByMovingOrthogonally 沿坐标轴方向小范围修正(Path.cpp:545-577)。
  • 影响:隔着墙、河或悬崖点击远处(超过 18 子格)时,原版角色沿直线走到障碍边就停下;本端预测器却按全图 A* 绕远路,而服务器停在障碍边,结果是客户端先跑出一段,再被 0x15 或重同步拉回来(橡皮筋)。起点的"最近可走"修正还会让角色先瞬移或斜走到别的格子。在地牢和野外的日常操作中就能触发。
  • 建议:客户端预测复用 1.13c 玩家路径的语义:Straight = Toward,距离 ≤18 时再 A*;MAXPATHLEN 78;nDistMax 73;使用同一碰撞掩码并考虑动态碰撞。不要自造 A*、拉绳或部分路径。
  • 已有 issue:—
> **1.13c 客户端保真度审计立项**(基准快照:`7bd1090` / `main @ 77a20c7`) > 证据标记说明:`V-data` = 1.13c MPQ 数据表 (`.txt` / `animdata.d2` / `.tbl` / `pal.pl2`);`V-src` = D2MOO 逆向源码;`V-bin` = 1.13c DLL 反汇编;`K` = 1.13c 公认行为。 ### 来源审计项:`motion-input#8` — [S1][R] 8. 本地寻路算法是自创的,和 1.13c 玩家路径(PATHTYPE_STRAIGHT)不同,导致预测路径与服务器分歧 - 位置:`src/client/motion/pathfind.ts:1-16`(设计说明)、`:59-73`(8 方向 + octile 启发)、`:168-218`(`findNearestWalkableLocal`)、`:220-244`(拉绳平滑)、`:306-461`(`findPathLocal`:`:314` maxExpanded 16384、`:316` nearestRadius 10、`:317` allowPartial、`:325` 连起点也做"最近可走"修正、`:357` 直视捷径、`:438` 部分路径) - 代码:`const maxExpanded = options.maxExpandedNodes ?? 16384`;`const resolvedStart = findNearestWalkableLocal(grid, startX, startY, nearestRadius)` - 原版: - 玩家的 DynamicPath 初始化为 `PATHTYPE_STRAIGHT`,`nDistMax` 73,`nIDAStarInitFScore` 70,`nMoveTestCollisionMask = COLLIDE_MASK_PLAYER_PATH`(V-src D2Common `Path.cpp:719-726`;路径函数表见 `Path.cpp:104-123`)。 - `PATH_Straight_Compute`(D2MOO 注释标为 1.13c D2Common 0x6FDB7AD0)先用 `PATH_Toward` 直线前进;只有受阻且起点到终点的距离平方 ≤ 18²(=324)时,才调用 `PATH_AStar_ComputePath` 绕行,否则保留直线结果(V-src `PathMisc.cpp:583-620`)。 - 路径点上限 MAXPATHLEN 78(`AStar.cpp:436`、`IDAStar.cpp:369`)。|Δ|>100 直接拒绝(`Path.cpp:394-397`)。目标被挡时用 `PATH_FindValidTargetCoordsByMovingOrthogonally` 沿坐标轴方向小范围修正(`Path.cpp:545-577`)。 - 影响:隔着墙、河或悬崖点击远处(超过 18 子格)时,原版角色沿直线走到障碍边就停下;本端预测器却按全图 A* 绕远路,而服务器停在障碍边,结果是客户端先跑出一段,再被 0x15 或重同步拉回来(橡皮筋)。起点的"最近可走"修正还会让角色先瞬移或斜走到别的格子。在地牢和野外的日常操作中就能触发。 - 建议:客户端预测复用 1.13c 玩家路径的语义:Straight = Toward,距离 ≤18 时再 A*;MAXPATHLEN 78;nDistMax 73;使用同一碰撞掩码并考虑动态碰撞。不要自造 A*、拉绳或部分路径。 - 已有 issue:—
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: troytt/diablo2-web#588
No description provided.