feat(playable): 首个 Mac 联网内测版 STB-01 soak 工具与发布状态文档

- 新增 script/playable_soak.sh:先做 soak 配置/资源校验,无 --allow-gameplay
  只校验不启动客户端;N(>=10) 次独立正常退出运行 + 墙钟 soak,失败即停止后续
  运行并记 BLOCKED;写本批次 release-manifest.json 后聚合
- run_client_gate.sh:确认的故障代理对所有 suite 启动(共享场景的退出运行也经代理);
  soak 超时下限只约束 soak 客户端(validate_soak 增加 soak_client 参数)
- 新增本地 127.0.0.1 故障代理、RSS 采样/内存判定、窗口/指标/流程模块及其测试
- forest_mob_render_test 输出 PASS/FAIL 标记,供 rendering_batch_test.sh 识别
- 新增 docs/FIRST-MAC-PLAYABLE-STATUS.md:如实记录 PASS/BLOCKED、已知问题与环境需求
- .gitignore 排除本地场景配置、凭据文件与运行输出

离线回归:rendering_batch_test.sh failures=0,playable_gate_test.sh PASS,
node 夹具测试 PASS。未联网运行,未重建候选包。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ft3kXpNdLbKEfg5uDLfqVF
This commit is contained in:
shenlei
2026-09-11 22:06:48 +09:00
co-authored by Claude Opus 5
parent 374d4165d8
commit f39a55fdd5
66 changed files with 9189 additions and 951 deletions
+20 -3
View File
@@ -894,8 +894,27 @@ func skill_context() -> Dictionary:
"arrow_count": _arrow_count,
"cur_hp": cur_hp,
"cur_sp": cur_sp,
"bow_distance": int(_bow_distance_bonus),
"target_distance": Callable(self, "skill_target_distance_cm"),
}
# rkInstMain.GetDistance(&rkInstTarget)(含 IS_HUGE_RACE 200)——施法射程判定与
# MODE_USE_SKILL 预约趋近共用同一量度,保证预约触发时 __UseSkill 必然在射程内。
func skill_target_distance_cm(vid: int) -> float:
if pc == null or pc.player == null or client == null:
return -1.0
var tnode: Node3D = net_world.node_for(vid) if net_world else null
if tnode == null:
return -1.0
var dist_cm: float = pc.player.global_position.distance_to(tnode.global_position) * CM
if _is_huge_race(int(client.get_entity(vid).get("race", 0))):
dist_cm -= HUGE_RACE_DIST_FIX_CM
return dist_cm
# __IsReservedUseSkill(dwSkillSlotIndex)
func is_use_skill_reserved(slot: int) -> bool:
return _reserved_mode == ReservedMode.USE_SKILL and _skill_slot_reserved == slot
func _process(dt: float) -> void:
# 击退动作播完 -> 解除击退闸门(动作时长驱动,非计时器)。
if _knock_down and player_view and player_view.has_method("is_in_hit_reaction") \
@@ -1160,9 +1179,7 @@ func _reserve_process_use_skill() -> void:
if rv.is_empty() or tnode == null:
_clear_reserved()
return
var dist_cm: float = pc.player.global_position.distance_to(tnode.global_position) * CM
if _is_huge_race(int(rv.get("race", 0))):
dist_cm -= HUGE_RACE_DIST_FIX_CM
var dist_cm := skill_target_distance_cm(_vid_reserved)
if dist_cm < _skill_range_reserved:
if _target_vid != _vid_reserved:
_target_vid = _vid_reserved