Implement playable Mac client and rendering validation

This commit is contained in:
shen
2026-09-11 14:58:22 +08:00
parent 1ab68bd06e
commit 374d4165d8
233 changed files with 6546 additions and 284 deletions
+33
View File
@@ -49,6 +49,7 @@ func _run() -> void:
_fail.append("资源缺失:%s" % p)
if _fail.is_empty():
report["effects"] = await _check_effect_resources(root)
report["scene"] = await _build_and_measure()
else:
report["scene"] = {"skipped": "前置检查已失败,不再装场景"}
@@ -65,6 +66,34 @@ func _run() -> void:
print("PKGRENDER: ", "PASS" if _fail.is_empty() else "FAIL")
get_tree().quit(0 if _fail.is_empty() else 1)
func _check_effect_resources(assets: String) -> Dictionary:
var dds_path := assets.path_join("PC/ymir work/pc/shaman/effect/shamanblackcore.dds")
var decoded := preload("res://ui/ui_assets.gd").load_dds_image(dds_path)
var dds_ok := decoded != null and not decoded.is_empty()
if not dds_ok:
_fail.append("包内 16 位技能 DDS 解码失败")
var mse_path := assets.path_join("PC/ymir work/pc/shaman/effect/noejeon_4_blow.mse")
var spec := preload("res://fx/mse.gd").new().parse_file(mse_path)
var effect := preload("res://fx/effect_player.gd").new()
effect.build(spec, assets)
add_child(effect)
# ParticleProcessMaterial shader variants are compiled on a deferred frame.
# Exercise a real lifecycle instead of freeing uninitialized GPU emitters.
await get_tree().process_frame
if DisplayServer.get_name() != "headless":
await RenderingServer.frame_post_draw
var special_materials := 0
for emitter in effect._emitters:
if emitter.material_override is ShaderMaterial:
special_materials += 1
if special_materials == 0:
_fail.append("包内真实技能未装配专用颜色材质")
effect.free()
await get_tree().process_frame
return {"dds_decoded": dds_ok, "special_materials": special_materials,
"dds_sha256": FileAccess.get_sha256(dds_path), "mse_sha256": FileAccess.get_sha256(mse_path),
"scope": "bundled DDS decode and real MSE material assembly; not skill pixels"}
# 包内和开发树的差异几乎都藏在这几个值里,先无条件记下来。
func _env() -> Dictionary:
var cands := {}
@@ -142,6 +171,10 @@ func _build_and_measure() -> Dictionary:
_fail.append("地图没装出来(灰底虚空)")
if surfaces == 0:
_fail.append("玩家节点下 0 个 surface")
if scene.world:
var trees: Dictionary = scene.world.get_load_report()
if int(trees.get("native_trees_placed", 0)) <= 0 or int(trees.get("proxy_trees_placed", -1)) != 0:
_fail.append("真实树木缺失或仍有代理回退:%s" % trees)
if not is_finite(feet_gap) or absf(feet_gap) > FEET_GAP_MAX:
_fail.append("feet_gap=%s 超出 %.3f" % [feet_gap, FEET_GAP_MAX])