39 lines
3.6 KiB
Markdown
39 lines
3.6 KiB
Markdown
# 🛡️ สัญญาทางเทคนิค: การบันทึกพาธเกมแบบทนทานต่อ 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:\` ในโค้ด
|