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:
@@ -124,3 +124,38 @@ func _run() -> void:
|
||||
await process_frame
|
||||
_ck(nw.node_for(2) != null, "main back in range -> culled entity rebuilt after its fade")
|
||||
_ck(int(added.get(2, 0)) == 2, "entity 2 rebuilt exactly once on re-entry")
|
||||
|
||||
await _dead_motion(fc, nw)
|
||||
|
||||
class AnimView extends Node3D:
|
||||
var states: Array[String] = []
|
||||
func set_anim_state(s: String) -> void:
|
||||
states.append(s)
|
||||
|
||||
# MAP-02 / CActorInstance::Die: a model plays NAME_DEAD only (no scene tilt), and
|
||||
# __SetMotion rejects every non-dead motion while the actor is dead — the
|
||||
# func/moving edge that arrives with the death must not restart WAIT.
|
||||
func _dead_motion(fc: FakeClient, nw: Node) -> void:
|
||||
nw.set_model_factory(func(d: Dictionary) -> Node3D:
|
||||
return AnimView.new() if int(d.get("race", 0)) == 2301 else null)
|
||||
var ent := fc.add(6, NEAR_CM + Vector2(300, 0), {"race": 2301, "ch_type": 2, "moving": true})
|
||||
fc.entity_spawned.emit(ent)
|
||||
await process_frame
|
||||
var view := nw.node_for(6) as AnimView
|
||||
_ck(view != null and view.states.back() == "run", "moving tree monster -> run requested")
|
||||
if view == null:
|
||||
return
|
||||
ent["moving"] = false
|
||||
ent["dead"] = true
|
||||
fc.entity_dead.emit(6)
|
||||
await create_tween().tween_interval(0.4).finished
|
||||
await process_frame
|
||||
_ck(view.states.back() == "dead", "death while moving keeps DEAD (reference __SetMotion ignores WAIT when dead): %s" % [view.states])
|
||||
_ck(is_zero_approx(view.rotation.x) and is_zero_approx(view.rotation.z), "model with motions is not tilted on death (rotation.x=%.2f)" % view.rotation.x)
|
||||
var capsule := fc.add(7, NEAR_CM + Vector2(600, 0), {"ch_type": 2})
|
||||
fc.entity_spawned.emit(capsule)
|
||||
var placeholder: Node3D = nw.node_for(7)
|
||||
capsule["dead"] = true
|
||||
fc.entity_dead.emit(7)
|
||||
await create_tween().tween_interval(0.4).finished
|
||||
_ck(placeholder != null and placeholder.rotation.x < -1.0, "placeholder capsule (no motions) still falls over as its only death cue")
|
||||
|
||||
Reference in New Issue
Block a user