- 토큰 전달 방식 변경: 명령줄 인자(-token) → 환경변수(A301_TOKEN)로 프로세스 목록 노출 방지 - 고정 설치 경로: %LOCALAPPDATA%\A301\로 런처 복사 후 레지스트리 등록 (Downloads 정리 시 깨짐 방지) - zip 추출 시 symlink 엔트리 스킵 (경로 탈출 방지) - fetchServerInfo 3회 재시도 (exponential backoff) - 다운로드 이어받기: Range 헤더 지원, 취소/오류 시 임시 파일 유지 - 416 응답 시 서버 파일 변경 감지하여 처음부터 재다운로드 - 단일 인스턴스 UX: 기존 창 FindWindow+SetForegroundWindow로 활성화 - uninstall 시 설치 디렉토리 정리 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
# 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" // 기술 식별자
|
|
```
|
|
|
|
## Install Location
|
|
|
|
- `install()` 시 런처를 `%LOCALAPPDATA%\A301\launcher.exe`로 복사 후 해당 경로를 레지스트리에 등록.
|
|
- 게임 파일(`A301.exe` 등)도 `%LOCALAPPDATA%\A301\`에 설치됨.
|
|
- 사용자가 원본 다운로드 파일을 삭제해도 프로토콜 핸들러가 정상 동작.
|
|
- 토큰은 명령줄이 아닌 `A301_TOKEN` 환경변수로 게임에 전달.
|
|
|
|
## Notes
|
|
|
|
- `extractZip()` — zip 내 최상위 디렉토리 1단계 제거 후 추출. `launcher.exe` 자신은 덮어쓰기 방지. Symlink 엔트리는 스킵.
|
|
- 레지스트리는 `HKCU` (현재 사용자) 에만 쓰므로 관리자 권한 불필요.
|
|
- `fetchServerInfo()` — 3회 재시도 (exponential backoff).
|
|
- `doDownload()` — Range 헤더로 이어받기 지원. 취소/오류 시 임시 파일 유지.
|