- main.go를 main()만 남기고 함수 분리 (game.go, protocol.go, ui.go) - 재시도 로직을 retryWithBackoff 공통 함수로 통합 - redeemTicketFrom 별도 HTTP 클라이언트 → apiClient 사용으로 통일 - doDownload에서 resumeOffset 이중 계산 제거 - extractZip에서 stripTopDir/extractFile 함수 분리 - downloadWithProgress에서 createProgressWindow 함수 분리 - DLL 선언을 DLL별로 그룹화, 상수를 역할별로 분리 - 전체 주석 한국어 통일 및 섹션 구분 추가 버그 수정: - ensureLauncher가 설치 경로 대신 실행 중인 경로를 해시하던 문제 수정 - uninstall 시 실행 중인 exe 삭제 실패 → 백그라운드 cmd로 대체 - moveContents에서 os.Remove 에러를 무시하던 문제 수정 - install/uninstall 메시지 통일, exitWithError 헬퍼 추가 - .gitignore에 *.exe 통일, ANALYSIS.md 삭제 - 빌드 명령에 git 태그 기반 버전 주입 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.9 KiB
2.9 KiB
CLAUDE.md
Build Command
C:\Users\98kim\sdk\go1.25.1\bin\go.exe build -ldflags="-H windowsgui -s -w -X main.version=$(git describe --tags --always)" -o launcher.exe .
-H windowsgui필수 — 없으면 실행 시 콘솔 창이 함께 열림.-X main.version=...— git 태그 기반 버전 자동 주입. 태그가 있으면v1.0.0, 태그 이후 커밋이 있으면v1.0.0-3-gabcdef형태.
Tech Stack
- Go 4파일 구조 (
main.go,ui.go,download.go,protocol.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
역할별 4파일 구조:
| 파일 | 담당 |
|---|---|
main.go |
진입점(main), 단일 인스턴스, handleURI, version |
ui.go |
Win32 DLL/proc 선언, WndProc, progress window, DPI, font, msgBox |
download.go |
HTTP 클라이언트, 다운로드/추출/해시, ensureGame, ensureLauncher |
protocol.go |
상수, URI 프로토콜 등록/해제, redeemTicket, fetchServerInfo |
주요 함수:
downloadWithProgress()— Win32 메시지 루프 직접 운영. 반드시 메인 고루틴에서 호출 (runtime.LockOSThread).fetchServerInfo()— 3회 재시도 (exponential backoff).ensureGame()—A301.exeSHA256 해시 비교 후 불일치 시 재다운로드.
UI Details
- DPI:
GetDpiForSystem()→dpiScale(px, dpi)함수로 모든 크기 동적 계산 - 진행 막대 색:
SetWindowTheme("", "")비주얼 스타일 비활성화 후PBM_SETBARCOLOR적용 - 다크 배경:
WM_CTLCOLORSTATIC핸들러에서hBrushBg반환 +SetBkMode(TRANSPARENT) - 타이틀 레이블(
titleLabelHwnd)만 강조색, 나머지 STATIC은 밝은 회색
Key Constants
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\에 설치됨. - 사용자가 원본 다운로드 파일을 삭제해도 프로토콜 핸들러가 정상 동작.
- 토큰은 커맨드라인(
-token)과A301_TOKEN환경변수 양쪽으로 게임에 전달.
Notes
extractZip()— zip 내 최상위 디렉토리 1단계 제거 후 추출.launcher.exe자신은 덮어쓰기 방지. Symlink 엔트리는 스킵.- 레지스트리는
HKCU(현재 사용자) 에만 쓰므로 관리자 권한 불필요. fetchServerInfo()— 3회 재시도 (exponential backoff).doDownload()— Range 헤더로 이어받기 지원. 취소/오류 시 임시 파일 유지.