- 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>
57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// version is set at build time via -ldflags "-X main.version=x.y.z"
|
|
var version = "dev"
|
|
|
|
func main() {
|
|
// DLL Hijacking 방어: DLL 탐색 경로를 System32로만 제한한다.
|
|
// 게임 폴더처럼 사용자가 파일을 쓸 수 있는 디렉토리에
|
|
// 악성 DLL이 심겨 있어도 로드되지 않는다.
|
|
// 반드시 다른 DLL이 로드되기 전 가장 먼저 호출해야 한다.
|
|
const loadLibrarySearchSystem32 = 0x00000800
|
|
kernel32.NewProc("SetDefaultDllDirectories").Call(loadLibrarySearchSystem32)
|
|
|
|
// Windows에게 "DPI는 내가 직접 처리한다"고 선언한다.
|
|
// 이 선언 없이는 OS가 창을 통째로 확대해 흐릿하게 표시한다.
|
|
// Per-Monitor V2: 모니터마다 DPI가 달라도 각각 대응 가능.
|
|
enableDPIAwareness()
|
|
|
|
// 단일 인스턴스 보장: 이미 실행 중이면 기존 창을 앞으로 가져오고 종료한다.
|
|
// 내부적으로 Named Mutex("Global\A301LauncherMutex")로 중복 실행을 감지한다.
|
|
if !acquireSingleInstance() {
|
|
activateExistingWindow()
|
|
return
|
|
}
|
|
|
|
// 인수 결정: 없으면 "install" (더블클릭 = 최초 설치)
|
|
arg := "install"
|
|
if len(os.Args) >= 2 {
|
|
arg = os.Args[1]
|
|
}
|
|
|
|
// a301://... URI는 별도 처리 (HasPrefix라 switch로 분기 불가)
|
|
if strings.HasPrefix(arg, protocolName+"://") {
|
|
if err := handleURI(arg); err != nil {
|
|
exitWithError(fmt.Sprintf("실행 실패:\n%v", err))
|
|
}
|
|
return
|
|
}
|
|
|
|
switch arg {
|
|
case "install":
|
|
handleInstall()
|
|
case "uninstall":
|
|
handleUninstall()
|
|
case "--version", "version":
|
|
msgBox("One of the plans 런처", fmt.Sprintf("버전: %s", version), mbOK|mbInfo)
|
|
default:
|
|
exitWithError(fmt.Sprintf("알 수 없는 명령: %s", arg))
|
|
}
|
|
}
|