diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2793db5 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,51 @@ +# CLAUDE.md + +## Build Command + +```bash +C:\Users\98kim\sdk\go1.25.1\bin\go.exe build -ldflags="-H windowsgui -s -w" -o launcher.exe . +``` + +`-H windowsgui` 필수 — 없으면 실행 시 콘솔 창이 함께 열림. + +## Tech Stack + +- **Go** 단일 파일 (`main.go`) +- **Win32 API** — `user32.dll`, `gdi32.dll`, `comctl32.dll`, `uxtheme.dll`, `shell32.dll` +- `golang.org/x/sys/windows` + `windows/registry` + +## Project Purpose + +"One of the plans" Windows 런처. +`a301://` 커스텀 URI 프로토콜 등록 → 게임 자동 다운로드/업데이트/실행. + +## Architecture + +모든 로직이 `main.go` 단일 파일에 있음: + +- **`enableDPIAwareness()`** — `SetProcessDpiAwarenessContext(PER_MONITOR_AWARE_V2)` 호출. `main()` 첫 줄에서 실행. +- **`downloadWithProgress()`** — Win32 메시지 루프 직접 운영. 반드시 메인 고루틴에서 호출 (`runtime.LockOSThread`). +- **`progressWndProc()`** — `WM_CTLCOLORSTATIC`으로 다크 테마 적용. `hBrushBg` 전역 변수 참조. +- **`setProgress(text, pct)`** — 다운로드 고루틴에서 호출해 레이블 텍스트와 진행 막대 동시 업데이트. +- **`fetchServerInfo()`** — `https://a301.api.tolelom.xyz/api/download/info` 조회. +- **`ensureGame()`** — `A301.exe` SHA256 해시 비교 후 불일치 시 재다운로드. + +## UI Details + +- DPI: `GetDpiForSystem()` → `dpiScale(px, dpi)` 함수로 모든 크기 동적 계산 +- 진행 막대 색: `SetWindowTheme("", "")` 비주얼 스타일 비활성화 후 `PBM_SETBARCOLOR` 적용 +- 다크 배경: `WM_CTLCOLORSTATIC` 핸들러에서 `hBrushBg` 반환 + `SetBkMode(TRANSPARENT)` +- 타이틀 레이블(`titleLabelHwnd`)만 강조색, 나머지 STATIC은 밝은 회색 + +## Key Constants + +```go +serverInfoURL = "https://a301.api.tolelom.xyz/api/download/info" +gameExeName = "A301.exe" // 기술 식별자 — 게임 표기명과 별개 +protocolName = "a301" // 기술 식별자 +``` + +## Notes + +- `extractZip()` — zip 내 최상위 디렉토리 1단계 제거 후 추출. `launcher.exe` 자신은 덮어쓰기 방지. +- 레지스트리는 `HKCU` (현재 사용자) 에만 쓰므로 관리자 권한 불필요. diff --git a/README.md b/README.md new file mode 100644 index 0000000..66859ab --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# One of the plans — Launcher + +Windows 전용 게임 런처. `a301://` 커스텀 URI 프로토콜을 등록하고, 웹에서 게임 시작 버튼 클릭 시 게임을 자동 다운로드/업데이트/실행합니다. + +## 빌드 + +```bash +# Go 1.24+ 필요 +go build -ldflags="-H windowsgui -s -w" -o launcher.exe . +``` + +`-H windowsgui` — 콘솔 창 없이 실행 (Win32 GUI 앱) +`-s -w` — 디버그 심볼 제거 (바이너리 크기 축소) + +## 사용법 + +| 실행 방법 | 동작 | +|-----------|------| +| `launcher.exe` (인자 없음) | `a301://` 프로토콜 등록 확인 다이얼로그 | +| `launcher.exe install` | 프로토콜 강제 등록 | +| `launcher.exe uninstall` | 프로토콜 제거 | +| `launcher.exe "a301://launch?token="` | 게임 실행 (웹에서 자동 호출) | + +## 게임 실행 흐름 + +``` +웹 "게임 시작" 클릭 + └─ a301://launch?token=JWT + └─ launcher.exe 실행 + ├─ 서버에서 최신 버전 정보 조회 (fileHash, url) + ├─ A301.exe 없음 또는 해시 불일치 → 다운로드 창 표시 + │ ├─ game.zip 다운로드 (진행률 표시) + │ └─ 압축 해제 (launcher.exe 자신은 덮어쓰기 방지) + └─ A301.exe -token 실행 +``` + +## UI + +다크 테마 Win32 창 (배경 `#2E2C2F`, 강조색 `#BACDB0`). +4K / FHD 해상도 모두 자연스럽게 표시 (DPI 인식 + 동적 스케일링). + +## 배포 구조 + +유저가 받는 구성: + +``` +(게임 폴더)/ +├── launcher.exe ← 이 파일 +└── A301.exe ← 런처가 자동 다운로드 +``` + +`launcher.exe`를 처음 실행하면 레지스트리에 `a301://` 프로토콜을 등록하고, 이후 웹에서 게임 시작 버튼을 누를 때마다 자동으로 이 런처가 실행됩니다. + +## 레지스트리 등록 경로 + +``` +HKCU\Software\Classes\a301\ +HKCU\Software\Classes\a301\shell\open\command → "launcher.exe" "%1" +``` + +## 의존성 + +- `golang.org/x/sys/windows` — Win32 API +- `golang.org/x/sys/windows/registry` — 레지스트리 접근