iter50-卡1:卡A(敌方状态个体化): 容器换代owner_key多桶(个体键单点/授予写点3处/死亡清/消费面随动/呈现逐卡)+断言V1-V8+armor_roll申报换代(个体键读数语义保留)+主角侧回归绿; 单元71套件+冒烟15项全绿
This commit is contained in:
1 parent
ab5d75a208
commit
e658492703
300 files changed
+609
-6039
No files matched your search
Executable → Regular
+20
-21
@@ -27,23 +27,22 @@
|
||||
# 窗口化运行会短暂弹 Godot 窗口(本机可开窗口径);禁改 --headless 跑本闸
|
||||
# (headless 无渲染面,探针内 fail-fast 护栏会红——那是护栏生效不是闸红)。
|
||||
# 用法: tools/render_gate.sh [game目录] 缺省 game 目录=脚本所在仓库的 game/(worktree 内自动指向该 worktree)
|
||||
# 依赖: tools/gate_platform.sh(双平台封装)+ python(PIL);Windows 侧另用 taskkill/PowerShell,macOS/Linux 走共享件;Godot 路径可用环境变量 GODOT_BIN 覆盖。
|
||||
# 依赖: Git Bash(coreutils timeout/taskkill) + PowerShell + python(PIL);Godot 路径可用环境变量 GODOT_BIN 覆盖。
|
||||
set -u
|
||||
G="${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}"
|
||||
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
. "$REPO/tools/gate_platform.sh" # 跨平台件(平台探测/路径形式/带超时执行/孤儿清杀)
|
||||
GAME="${1:-$REPO/game}"
|
||||
GAME_WIN="$(gate_game_path "$GAME")" # Godot --path 接受形式(Windows 混合斜杠,其他平台原样)
|
||||
GOLDEN="$REPO/game/tests/golden/$(gate_platform_id)" # 本平台基线目录(按平台各存,比较器同口径)
|
||||
GAME_WIN="$(cygpath -m "$GAME")" # Godot --path 需 Windows 形式
|
||||
TMP="$(mktemp -d /tmp/rendergate_XXXXXX)"
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
_rc=0
|
||||
|
||||
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(实现单点在 gate_platform.sh,双平台)
|
||||
gate_orphans "$GAME_WIN"
|
||||
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(console wrapper+真引擎都算)
|
||||
printf "Get-CimInstance Win32_Process -Filter \"Name like 'Godot%%'\" | Where-Object { \$_.CommandLine -like '*%s*' } | ForEach-Object { \$_.ProcessId }\n" "$GAME_WIN" > "$TMP/k.ps1"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "$(cygpath -w "$TMP/k.ps1")" 2>/dev/null | tr -d '\r'
|
||||
}
|
||||
kill_orphans() {
|
||||
gate_kill_orphans "$GAME_WIN"
|
||||
local p; for p in $(orphans); do taskkill //F //PID "$p" >/dev/null 2>&1; done
|
||||
}
|
||||
|
||||
scan_log() { # scan_log <段名> <日志>——脚本错误扫描;日志不可读(error_scan exit 2)同判红
|
||||
@@ -58,7 +57,7 @@ scan_log() { # scan_log <段名> <日志>——脚本错误扫描;日志不
|
||||
# 冷检出刷导入(.godot 不入 git,fresh worktree 首跑一次性付)
|
||||
if [ ! -f "$GAME/.godot/uid_cache.bin" ]; then
|
||||
echo "[render_gate] 冷检出:editor --quit 刷导入(一次性,可到 1-2 分钟)"
|
||||
gate_run_timeout 300 "$TMP/refresh.log" "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
|
||||
timeout 300 "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
|
||||
kill_orphans
|
||||
fi
|
||||
|
||||
@@ -67,13 +66,13 @@ if [ "$pre" -gt 0 ]; then echo "[render_gate] 预清本闸残留 Godot×$pre"; k
|
||||
|
||||
echo "======== shot_probe 七屏截图 → shot_checker A-D ========"
|
||||
SHOT="$TMP/shots"
|
||||
gate_run_timeout 180 "$TMP/shot.log" "$G" --path "$GAME_WIN" --quit-after 3000 res://probe/shot_probe.tscn -- "$SHOT"
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/shot_probe.tscn -- "$SHOT" >"$TMP/shot.log" 2>&1
|
||||
st=$?; kill_orphans
|
||||
grep -E "\[shot_probe\]" "$TMP/shot.log" | tail -12
|
||||
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
|
||||
echo "[render_gate] FAIL — shot_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
|
||||
elif [ "$st" -ne 0 ] || ! grep -q "问题=0" "$TMP/shot.log"; then
|
||||
echo "[render_gate] FAIL — shot_probe 未干净完成(exit=${st},缺失屏/空文件/路径断裂见上)"; _rc=1
|
||||
echo "[render_gate] FAIL — shot_probe 未干净完成(exit=$st,缺失屏/空文件/路径断裂见上)"; _rc=1
|
||||
fi
|
||||
if [ "$_rc" -eq 0 ]; then
|
||||
python tools/shot_checker.py "$SHOT" shot_menu.png shot_settings.png shot_career.png shot_camp.png shot_level.png shot_battle.png shot_status.png | sed 's/^/[render_gate] /'
|
||||
@@ -84,13 +83,13 @@ scan_log "shot_probe" "$TMP/shot.log"
|
||||
|
||||
echo "======== fx_shot_probe 三时刻取证(Q7) ========"
|
||||
FX="$TMP/fxshots"
|
||||
gate_run_timeout 180 "$TMP/fx.log" "$G" --path "$GAME_WIN" --quit-after 3000 res://probe/fx_shot_probe.tscn -- "$FX"
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/fx_shot_probe.tscn -- "$FX" >"$TMP/fx.log" 2>&1
|
||||
st=$?; kill_orphans
|
||||
grep -E "\[fx_shot_probe\]" "$TMP/fx.log" | tail -4
|
||||
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
|
||||
echo "[render_gate] FAIL — fx_shot_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
|
||||
elif [ "$st" -ne 0 ]; then
|
||||
echo "[render_gate] FAIL — fx_shot_probe 退出码=${st}(取证失败=闸红)"; _rc=1
|
||||
echo "[render_gate] FAIL — fx_shot_probe 退出码=$st(取证失败=闸红)"; _rc=1
|
||||
fi
|
||||
scan_log "fx_shot_probe" "$TMP/fx.log"
|
||||
fx_evidence() { # 取证双检:模式文件存在且非零字节(零字节/缺失任一即 FAIL——Q7)
|
||||
@@ -109,13 +108,13 @@ fx_evidence "fx_final.png" 1
|
||||
|
||||
echo "======== board_shot_probe L1-L3 取证(Q7) ========"
|
||||
BD="$TMP/boardshots"
|
||||
gate_run_timeout 180 "$TMP/bd.log" "$G" --path "$GAME_WIN" --quit-after 3000 res://probe/board_shot_probe.tscn -- "$BD"
|
||||
timeout 180 "$G" --path "$GAME_WIN" res://probe/board_shot_probe.tscn -- "$BD" >"$TMP/bd.log" 2>&1
|
||||
st=$?; kill_orphans
|
||||
grep -E "\[board_shot\]" "$TMP/bd.log" | tail -6
|
||||
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
|
||||
echo "[render_gate] FAIL — board_shot_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
|
||||
elif [ "$st" -ne 0 ]; then
|
||||
echo "[render_gate] FAIL — board_shot_probe 退出码=${st}(取证失败=闸红)"; _rc=1
|
||||
echo "[render_gate] FAIL — board_shot_probe 退出码=$st(取证失败=闸红)"; _rc=1
|
||||
fi
|
||||
scan_log "board_shot_probe" "$TMP/bd.log"
|
||||
for b in board_L1_dungeon.png board_L2_underdark.png board_L3_deep_underdark.png board_meta.json; do
|
||||
@@ -123,8 +122,8 @@ for b in board_L1_dungeon.png board_L2_underdark.png board_L3_deep_underdark.png
|
||||
done
|
||||
|
||||
echo "======== 棋盘 golden 逐像素(T2——裁剪→对比,容差 provisional) ========"
|
||||
if [ ! -d "$GOLDEN" ]; then
|
||||
echo "[render_gate] FAIL — 本平台($(gate_platform_id))基线目录缺失:${GOLDEN}(基线按平台各存、在库=验收断言②)"; _rc=1
|
||||
if [ ! -d "$REPO/game/tests/golden" ]; then
|
||||
echo "[render_gate] FAIL — game/tests/golden/ 基线目录缺失(基线在库=验收断言②)"; _rc=1
|
||||
elif [ ! -s "$BD/board_meta.json" ]; then
|
||||
echo "[render_gate] SKIP — board_meta.json 缺失(取证段已红),golden 对比不判"
|
||||
else
|
||||
@@ -137,7 +136,7 @@ else
|
||||
assets/art/board/terrain_wall_n_dungeon.png assets/art/board/terrain_floor_dungeon_1.png \
|
||||
assets/art/board/terrain_wall_n_underdark.png assets/art/board/terrain_floor_underdark_1.png \
|
||||
assets/art/board/terrain_wall_n_deep_underdark.png assets/art/board/terrain_floor_deep_underdark_1.png; do
|
||||
[ -f "$GAME/$a" ] || { echo "[render_gate] FAIL — 棋盘素材缺位: ${a}(Q5:基线锚素材齐盘态,缺盘不得出验收结论)"; _asset_miss=1; }
|
||||
[ -f "$GAME/$a" ] || { echo "[render_gate] FAIL — 棋盘素材缺位: $a(Q5:基线锚素材齐盘态,缺盘不得出验收结论)"; _asset_miss=1; }
|
||||
done
|
||||
if [ "$_asset_miss" -eq 0 ]; then
|
||||
CROP="$TMP/crop"
|
||||
@@ -155,8 +154,8 @@ else
|
||||
fi
|
||||
|
||||
echo "======== 菜单 golden 逐像素(迭代 28 T4——启动态全屏基线)========"
|
||||
if [ ! -s "$GOLDEN/menu_boot.png" ]; then
|
||||
echo "[render_gate] FAIL — $GOLDEN/menu_boot.png 基线缺失(菜单 golden 未建——本平台跑 tools/golden_baseline_refresh.sh --menu)"; _rc=1
|
||||
if [ ! -s "$REPO/game/tests/golden/menu_boot.png" ]; then
|
||||
echo "[render_gate] FAIL — game/tests/golden/menu_boot.png 基线缺失(菜单 golden 未建——tools/golden_baseline_refresh.sh --menu)"; _rc=1
|
||||
elif [ ! -s "$SHOT/shot_menu.png" ]; then
|
||||
echo "[render_gate] SKIP — shot_menu.png 缺失(shot_probe 段已红),菜单 golden 不判"
|
||||
elif [ ! -f "$GAME/assets/fonts/ui_font_fusion_pixel_zh_hans.ttf" ] || [ ! -f "$GAME/assets/art/ui/button_stone.png" ]; then
|
||||
@@ -173,8 +172,8 @@ fi
|
||||
|
||||
echo "======== 残留检查(批末闸) ========"
|
||||
left="$(orphans | wc -l | tr -d ' ')"
|
||||
total="$(gate_godot_count_all)"
|
||||
echo "本闸残留 Godot=${left}(必须0) 全局 Godot 进程=${total}(其他会话的仅报数不算账)"
|
||||
total="$(tasklist 2>/dev/null | grep -ci '^Godot' || true)"
|
||||
echo "本闸残留 Godot=$left(必须0) 全局 Godot 进程=$total(其他会话的仅报数不算账)"
|
||||
if [ "$left" -ne 0 ]; then echo "[render_gate] FAIL — 本闸残留未清零"; kill_orphans; _rc=1; fi
|
||||
if [ "$_rc" -eq 0 ]; then echo "[render_gate] 全绿"; else echo "[render_gate] 存在 FAIL,见上"; fi
|
||||
exit "$_rc"
|
||||
Reference in new issue
Block a user