# 🛡️ สัญญาทางเทคนิค: การบันทึกพาธเกมแบบทนทานต่อ Crash (Game Selection Persistence) เอกสารนี้ระบุสถาปัตยกรรมการบันทึกและอ่านพาธที่ตั้งของไฟล์ตัวเกม (`StarRail.exe`) ใน [`internal/fs-service/game-selection.go`](../internal/fs-service/game-selection.go) --- ## 1. ที่มาและปัญหาความเสียหายของไฟล์คอนฟิก (The Corruption Problem) ในโปรเจกต์ต้นแบบเดิม การบันทึกพาธของเกมใช้ฟังก์ชันมาตรฐาน `os.WriteFile` ซึ่งมีจุดอ่อนร้ายแรงบนระบบปฏิบัติการ Windows: * หากเครื่องคอมพิวเตอร์ดับกะทันหัน ไฟตก หรือ Launcher เกิด Crash ในเสี้ยววินาทีที่กำลังเขียนไฟล์ * ไฟล์ `game-selection.json` จะกลายเป็น **ไฟล์ว่างเปล่าขนาด 0 ไบต์ (Zero-Byte Corrupted File)** * เมื่อเปิด Launcher ขึ้นมาใหม่ โปรแกรมจะไม่สามารถอ่าน JSON ได้ ส่งผลให้ผู้ใช้ต้องค้นหาและเลือกพาธเกมใหม่ซ้ำซาก --- ## 2. โซลูชัน: Atomic Write ผ่าน Windows API `MoveFileEx` เพื่อแก้ไขปัญหานี้ G-Launcher จึงนำรูปแบบ **Atomic Write** ที่ผสานมาจาก Sunbringer มาใช้งานอย่างเคร่งครัด: ``` [ผู้ใช้เลือกพาธเกม: C:\Games\StarRail.exe] │ ▼ 1. เขียนข้อมูล JSON ลงในไฟล์ชั่วคราว (.tmp) └── %APPDATA%\g-launcher\game-selection.json.tmp │ ▼ 2. Flush ข้อมูลลงดิสก์จริง (Sync to Storage) └── file.Sync() เพื่อให้แน่ใจว่าข้อมูลถูกเขียนลงฮาร์ดดิสก์/SSD จริง ไม่ค้างใน OS Cache │ ▼ 3. สลับไฟล์ด้วย Windows Native API MoveFileEx └── MoveFileExW(tempPath, targetPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) ``` ### คุณสมบัติของ `MoveFileEx`: * **Atomic Operation:** บนระบบไฟล์ NTFS การสลับไฟล์ด้วย `MoveFileEx` ถือเป็น Atomic Operation กล่าวคือ ไฟล์จะเปลี่ยนเป็นเวอร์ชันใหม่ทันที หรือหากเกิดเหตุขัดข้อง ไฟล์เดิมก็จะยังคงอยู่สมบูรณ์ 100% ไม่มีทางเกิดไฟล์ 0 ไบต์ * **No Hardcoding:** ตำแหน่งไฟล์คอนฟิกถูกสร้างขึ้นโดยใช้ `os.UserConfigDir()` ร่วมกับ `filepath.Join(...)` ซึ่งจะได้พาธมาตรฐาน `%APPDATA%\g-launcher\game-selection.json` โดยไม่ฝังชื่อไดรฟ์ `C:\` ในโค้ด