150 lines
5.3 KiB
Bash
150 lines
5.3 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# BT27 검증용 도우미 — source 해서 쓴다
|
||
|
|
export PYTHONIOENCODING=utf-8
|
||
|
|
P="C:/BurningTimes/FirstRising"
|
||
|
|
SP="C:/Users/sw/AppData/Local/Temp/claude/E--BurningTimes/3562a2c1-e88a-4143-b7ec-e74c317778d8/scratchpad"
|
||
|
|
|
||
|
|
# ev <스크립트 이름> [인수...] — eval_file 실행 후 결과 글자만 출력
|
||
|
|
ev() {
|
||
|
|
local f="$1"; shift
|
||
|
|
if [ $# -gt 0 ]; then printf "%s" "$*" > "$SP/eval/args.txt"; fi
|
||
|
|
unity command eval_file --file "$SP/eval/$f.cs" --project-path "$P" --format json --no-banner 2>&1 | python -c "
|
||
|
|
import sys, json
|
||
|
|
raw = sys.stdin.read()
|
||
|
|
try:
|
||
|
|
d = json.loads(raw)
|
||
|
|
except Exception as ex:
|
||
|
|
print('PARSE FAIL', raw[:600]); sys.exit(0)
|
||
|
|
r = (d.get('data') or {}).get('result')
|
||
|
|
if isinstance(r, dict):
|
||
|
|
print(r.get('result'))
|
||
|
|
if r.get('error'): print('EVAL ERROR', r.get('error'), r.get('errorDetails'))
|
||
|
|
for x in (r.get('diagnostics') or []): print('DIAG', x)
|
||
|
|
else:
|
||
|
|
print(r)
|
||
|
|
if d.get('errors'): print('ERR', d.get('errors'))
|
||
|
|
"
|
||
|
|
}
|
||
|
|
|
||
|
|
# st — Play 여부 단독 확인
|
||
|
|
st() {
|
||
|
|
unity command editor_status --project-path "$P" --format json --no-banner 2>&1 | grep -E '"playMode"|"compiling"|"status"|domainReload' | tr -d ' \n'; echo
|
||
|
|
}
|
||
|
|
|
||
|
|
# errs — 콘솔 오류 목록
|
||
|
|
errs() {
|
||
|
|
unity command get_console_logs --severity error --project-path "$P" --format json --no-banner 2>&1 | python -c "
|
||
|
|
import sys, json
|
||
|
|
d = json.loads(sys.stdin.read())
|
||
|
|
r = (d.get('data') or {}).get('result') or {}
|
||
|
|
print('errors total', r.get('total'))
|
||
|
|
seen = {}
|
||
|
|
for l in (r.get('logs') or []):
|
||
|
|
m = (l.get('message') or '')[:300]
|
||
|
|
seen[m] = seen.get(m, 0) + 1
|
||
|
|
for m, c in seen.items():
|
||
|
|
print(' x%d %s' % (c, m.replace('\n', ' | ')))
|
||
|
|
"
|
||
|
|
}
|
||
|
|
|
||
|
|
# warns — 콘솔 경고 목록
|
||
|
|
warns() {
|
||
|
|
unity command get_console_logs --severity warning --project-path "$P" --format json --no-banner 2>&1 | python -c "
|
||
|
|
import sys, json
|
||
|
|
d = json.loads(sys.stdin.read())
|
||
|
|
r = (d.get('data') or {}).get('result') or {}
|
||
|
|
print('warnings total', r.get('total'))
|
||
|
|
seen = {}
|
||
|
|
for l in (r.get('logs') or []):
|
||
|
|
m = (l.get('message') or '')[:300]
|
||
|
|
seen[m] = seen.get(m, 0) + 1
|
||
|
|
for m, c in seen.items():
|
||
|
|
print(' x%d %s' % (c, m.replace('\n', ' | ')))
|
||
|
|
"
|
||
|
|
}
|
||
|
|
|
||
|
|
# cap <이름> [너비] [높이] — 게임 화면을 찍어 스크래치패드에 저장(검정 여백은 잘라낸다)
|
||
|
|
cap() {
|
||
|
|
local name="$1"; local w="${2:-1080}"; local h="${3:-1920}"
|
||
|
|
unity command capture_game_view --source screen --width "$w" --height "$h" --project-path "$P" --format json --no-banner 2>&1 | python -c "
|
||
|
|
import sys, json, base64, io
|
||
|
|
d = json.loads(sys.stdin.read())
|
||
|
|
r = (d.get('data') or {}).get('result') or {}
|
||
|
|
def find(o):
|
||
|
|
if isinstance(o, dict):
|
||
|
|
for k, v in o.items():
|
||
|
|
if isinstance(v, str) and len(v) > 1000:
|
||
|
|
return v
|
||
|
|
f = find(v)
|
||
|
|
if f: return f
|
||
|
|
if isinstance(o, list):
|
||
|
|
for v in o:
|
||
|
|
f = find(v)
|
||
|
|
if f: return f
|
||
|
|
return None
|
||
|
|
b = find(r)
|
||
|
|
if not b:
|
||
|
|
print('NO IMAGE', json.dumps(d)[:500]); sys.exit(0)
|
||
|
|
data = base64.b64decode(b)
|
||
|
|
out = r'$SP/cap/$name.png'
|
||
|
|
try:
|
||
|
|
from PIL import Image
|
||
|
|
im = Image.open(io.BytesIO(data)).convert('RGB')
|
||
|
|
gray = im.convert('L').point(lambda p: 255 if p > 10 else 0)
|
||
|
|
box = gray.getbbox()
|
||
|
|
if box: im = im.crop(box)
|
||
|
|
mx = 900
|
||
|
|
if max(im.size) > mx:
|
||
|
|
k = mx / float(max(im.size))
|
||
|
|
im = im.resize((int(im.size[0] * k), int(im.size[1] * k)), Image.LANCZOS)
|
||
|
|
im.save(out)
|
||
|
|
print('saved', out, im.size)
|
||
|
|
except ImportError:
|
||
|
|
open(out, 'wb').write(data)
|
||
|
|
print('saved raw', out, len(data))
|
||
|
|
"
|
||
|
|
}
|
||
|
|
|
||
|
|
# rc — 재컴파일하고 끝날 때까지 기다린 뒤 결과와 콘솔 오류를 보여 준다(Play 여부는 먼저 st 로 따로 확인할 것)
|
||
|
|
rc() {
|
||
|
|
unity command recompile --project-path "$P" --format json --no-banner 2>&1 | grep -E '"status"' | head -1
|
||
|
|
local s=""
|
||
|
|
for i in $(seq 1 100); do
|
||
|
|
sleep 3
|
||
|
|
s=$(unity command recompile_status --project-path "$P" --format json --no-banner 2>&1 | grep -E '"result"' | head -1)
|
||
|
|
case "$s" in *'status\":\"completed'*|*'status\":\"up_to_date'*|*'status\":\"idle'*|*'failed\":true'*) break;; esac
|
||
|
|
done
|
||
|
|
echo "recompile: $s"
|
||
|
|
errs
|
||
|
|
}
|
||
|
|
|
||
|
|
# bld — 보스 패턴 빌드(분리 실행) 후 보고서 머리·꼬리와 콘솔 오류
|
||
|
|
bld() {
|
||
|
|
local J=$(unity command eval_file --file "$SP/eval/boss_build.cs" --project-path "$P" --detach --format json --no-banner 2>&1 | grep -o '"jobId": *"[a-f0-9]*"' | grep -o '[a-f0-9]\{32\}')
|
||
|
|
unity job wait "$J" --project-path "$P" --format json --no-banner 2>&1 | grep -E '"state"|"result": "|"executionTimeMs"|"error": "'
|
||
|
|
head -3 "$P/Assets/BurningTimes/Boss/Data/BuildReport.txt"
|
||
|
|
grep -n "소환물\|\[주의\]" "$P/Assets/BurningTimes/Boss/Data/BuildReport.txt"
|
||
|
|
tail -3 "$P/Assets/BurningTimes/Boss/Data/BuildReport.txt"; echo
|
||
|
|
errs
|
||
|
|
}
|
||
|
|
|
||
|
|
# play — Play 진입 후 월드 준비까지 기다린다
|
||
|
|
play() {
|
||
|
|
unity command clear_console --project-path "$P" --format json --no-banner >/dev/null 2>&1
|
||
|
|
unity command editor_play --project-path "$P" --format json --no-banner 2>&1 | grep -E '"success"' | head -1
|
||
|
|
for i in $(seq 1 60); do
|
||
|
|
sleep 3
|
||
|
|
local r=$(ev probe 2>&1 | head -1)
|
||
|
|
case "$r" in *"config=True"*"player=True"*"world=True"*) echo "$i $r"; break;; esac
|
||
|
|
done
|
||
|
|
sleep 5
|
||
|
|
}
|
||
|
|
|
||
|
|
# stop — 감시자를 빼고 Play 를 끝낸다
|
||
|
|
stop() {
|
||
|
|
ev monitor_remove
|
||
|
|
unity command editor_stop --project-path "$P" --format json --no-banner 2>&1 | grep -E '"success"' | head -1
|
||
|
|
sleep 4
|
||
|
|
st
|
||
|
|
}
|