docs: enrich Doc/ with deep-dive technical contracts, traps, and handoff

This commit is contained in:
CAtlas0784 committed 2026-10-30 21:40:42 +07:00
1 parent 3411e5b058
commit fc262f8331
9 files changed
+502 -8

No files matched your search

+112
View File
@@ -0,0 +1,112 @@
# ส่งต่องาน G-Launcher (G-LAUNCHER-HANDOFF)
> เอกสารส่งต่อสถานะทางเทคนิค ฉบับสมบูรณ์สำหรับ AI Agent และนักพัฒนา
> อ้างอิงมาตรฐานการบันทึกสถานะตามแบบฉบับ `GaC-hkrpg-go/docs`
---
> **อ่านหัวข้อนี้ก่อนเริ่มงานทุกครั้ง (CRITICAL NOTICE):**
> - **Active Branch:** ทำงานบนสาขา **`Dev`** เท่านั้น (ห้ามแตะต้องหรือ push ตรงเข้า main)
> - **Remote URL:** `https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher.git`
> - **หลักการตัดสินใจ:** แยกคำว่า **“มีโค้ดใน source”**, **“build ผ่าน”**, **“วางไฟล์แล้ว”** และ **“ผู้ใช้ยืนยันผลจริงแล้ว”** ออกจากกันอย่างเด็ดขาด
> - **กฎเหล็กสถาปัตยกรรม:**
> 1. แก้ที่ Go Backend (`internal/`, `pkg/`) ก่อน Frontend UI เสมอ และต้องรัน `go vet ./...` ผ่าน 100% ก่อนแตะ UI
> 2. ห้าม Hardcode IP, URL, Port, หรือ Drive Letter ใดๆ ทั้งสิ้น (รวมไว้ที่ [`pkg/constant/constant.go`](../pkg/constant/constant.go))
> 3. วงจรอัปเดต: **โหลดลง Temp -> Build ใน Temp -> แทนที่ไฟล์เดิม -> ลบ Temp ทิ้ง 100%**
อัปเดตล่าสุด: 30 ตุลาคม 2026 (Asia/Bangkok) | สถานะ Git: Branch `Dev` สะอาด (All clean)
---
## 1. ตารางสรุปสถานะระบบ (System Implementation & Verification Matrix)
| ระบบย่อย (Subsystem) | โค้ดใน Source | Build ผ่าน | Deploy/Run | ยืนยันผลจริง | รายละเอียดทางเทคนิค / ไฟล์อ้างอิง |
| :--- | :---: | :---: | :---: | :---: | :--- |
| **Go Backend Core Services** | ✅ | ✅ | ✅ | ✅ | บริการ 5 ตัวลงทะเบียนใน `main.go` ผ่าน `app.RegisterService` |
| **Wails v3 TypeScript Bindings** | ✅ | ✅ | ✅ | ✅ | สร้างผ่าน `wails3 generate bindings` ลงที่ `frontend/bindings/` |
| **Frontend UI (React 19 + DaisyUI)** | ✅ | ✅ | ✅ | ✅ | React 19 + Vite + Tailwind v4 + DaisyUI v5 คอมไพล์ผ่าน 100% |
| **Auto-Updater & Bootstrap Script** | ✅ | ✅ | ✅ | ✅ | `scripts/bootstrap.ps1` ทำงานแบบ Temp Build + Cleanup 100% |
| **One-Click Batch Launcher** | ✅ | ✅ | ✅ | ✅ | `update-and-build.bat` เรียกใช้ PowerShell Bypass UTF-8 BOM |
| **Go Backend Source Updater** | ✅ | ✅ | ✅ | ⚠️ รอ UI เรียก | `BuildAndUpdateFromSource` ใน `internal/git-service/launcher.go` |
| **Portable MinGit Runtime** | ✅ | ✅ | ✅ | ✅ | `internal/git-service/git_runtime.go` ดึง MinGit x64 อัตโนมัติ |
| **Atomic Game Path Persistence** | ✅ | ✅ | ✅ | ✅ | `internal/fs-service/game-selection.go` ใช้ Windows `MoveFileEx` |
| **Zift Archive Patching (.ziff)** | ✅ | ✅ | ✅ | ⚠️ รอด่านทดสอบ | `internal/diff-service/ziff.go` ครอบ `zift.exe` |
| **HPatchz Delta Patching (.hdiff)** | ✅ | ✅ | ✅ | ⚠️ รอด่านทดสอบ | `internal/diff-service/hpatchz.go` ครอบ `hpatchz.exe` |
| **Thai Mod Engine (ExcelData)** | ✅ | ✅ | ✅ | ⚠️ รอเกมจริง | `internal/language-service/thai-patch.go` มีระบบ `.backup` |
| **Multi-Language (i18n)** | ✅ | ✅ | ✅ | ✅ | 6 ภาษา (`th`, `en`, `ja`, `ko`, `vi`, `zh`) ใน `frontend/public/locales/` |
| **Standalone Tool Extraction** | ✅ | ✅ | ✅ | ✅ | แตกไฟล์ `assets/` (`7za.exe`, `hpatchz.exe`, `zift.exe`) ลง `bin/` |
---
## 2. กับดักและบทเรียนทางเทคนิคที่ห้ามพลาด (Technical Traps & Pitfalls)
### กับดักที่ 1: Wails v3 Embed Directive ขาดไม่ได้
* **อาการ:** `go build` หรือ `go vet` ฟ้อง `pattern all:frontend/dist: no matching files found`
* **สาเหตุ:** `main.go` มีการประกาศ `//go:embed all:frontend/dist` ซึ่ง Compiler ของ Go จะปฏิเสธการคอมไพล์ทันทีหากโฟลเดอร์ `frontend/dist` ว่างเปล่าหรือไม่มีอยู่จริง
* **แนวทางแก้ไข:** ต้องรัน `npm --prefix frontend run build` ก่อน หรือมีไฟล์ `.gitkeep` วางอยู่ใน `frontend/dist/` เสมอ
### กับดักที่ 2: Windows PowerShell 5.1 กับปัญหา UTF-8 Encoding
* **อาการ:** รัน `powershell -File script.ps1` แล้วพังด้วยข้อผิดพลาดไวยากรณ์ เช่น `Unexpected token '}'` หรือ `You must provide a value expression following the '-' operator`
* **สาเหตุ:** `powershell.exe` (เวอร์ชัน 5.1 เดิมของ Windows) จะอ่านไฟล์ข้อความภาษาไทยด้วย System ANSI Code Page (CP874 หรือ Windows-1252) หากไฟล์ถูกบันทึกเป็น UTF-8 แบบไม่มี BOM ไบต์อักขระภาษาไทยบางตัวจะถูกตีความเป็นเครื่องหมายคำพูด (`"`) หรือเครื่องหมายลบ (`-`) ทำให้ Parser พัง
* **แนวทางแก้ไข:** ไฟล์ `.ps1` ที่มีอักขระสองไบต์หรือภาษาไทย **ต้องบันทึกด้วย UTF-8 with BOM (`[System.Text.Encoding]::UTF8`) เสมอ**
### กับดักที่ 3: Windows Process Lock ขณะอัปเดตตัวเอง
* **อาการ:** `go build` หรือการคัดลอกไฟล์ทับ `bin/G-Launcher.exe` ล้มเหลวด้วย `Access is denied`
* **สาเหตุ:** Windows ห้ามเขียนทับหรือลบ Executable (`.exe`) ที่โปรเซสกำลังทำงานอยู่
* **แนวทางแก้ไข:** **เปลี่ยนชื่อไฟล์เดิมแทน (Rename)** โดยเปลี่ยนชื่อ `G-Launcher.exe` ที่กำลังรันอยู่เป็น `G-Launcher.exe.old` (Windows อนุญาตให้ rename process executable ที่กำลังรันได้) จากนั้นจึงย้ายไฟล์ executable ตัวใหม่เข้ามาเสียบแทนที่ แล้วจึงสั่งเปิดตัวใหม่และลบตัวเก่า
### กับดักที่ 4: Wails v3 Binding Crash หากแก้ UI ก่อน Backend
* **อาการ:** หน้าต่าง Launcher เปิดขึ้นมาแล้วขาวสนิท จอดำ หรือ DevTools คอนโซลขึ้น `Cannot read properties of undefined`
* **สาเหตุ:** Frontend ฝั่ง React เรียกใช้งาน IPC method ผ่าน `@bindings/...` หาก Backend ยังไม่ได้ประกาศ method นั้น หรือ type signature ไม่ตรงกัน Wails IPC Gateway จะเกิด Unhandled Exception
* **แนวทางแก้ไข:** ปฏิบัติตาม **System-First Rule** โดยแก้ Go service ให้เสร็จ -> รัน `go vet ./...` -> รัน `wails3 generate bindings` -> ตรวจดู TypeScript interface -> จึงค่อยเริ่มเขียน UI
### กับดักที่ 5: Git Interactive Terminal Freeze
* **อาการ:** รัน `git push` หรือ `git clone` ผ่านสคริปต์อัตโนมัติแล้วโปรเซสค้าง (Hang) ไม่ยอมสิ้นสุด
* **สาเหตุ:** Git พยายามเปิด Interactive Prompt เพื่อถาม Username/Password ในเทอร์มินัลที่ไม่มี TTY
* **แนวทางแก้ไข:** ต้องตั้งค่า `$env:GIT_TERMINAL_PROMPT = "0"` ใน PowerShell หรือ `os.Setenv("GIT_TERMINAL_PROMPT", "0")` ใน Go ก่อนเรียกคำสั่ง Git เสมอ
---
## 3. รายละเอียดสถาปัตยกรรมระบบอัปเดต (Isolated Updater Architecture)
กระบวนการอัปเดตทั้งใน [`scripts/bootstrap.ps1`](../scripts/bootstrap.ps1) และ [`internal/git-service/launcher.go`](../internal/git-service/launcher.go) ปฏิบัติตามกฎ 4 ขั้นตอน:
```
[ผู้ใช้สั่งอัปเดต]
│
▼
1. โหลดลงโฟลเดอร์ชั่วคราว (Temp Workspace)
├── สร้างโฟลเดอร์: temp/build_workspace หรือ os.MkdirTemp
└── Clone ซอร์สโค้ด: git clone --depth 1 --branch Dev <RepoUrl> <TempDir>
│
▼
2. คอมไพล์ในโฟลเดอร์ชั่วคราว (Isolated Build)
├── npm install --no-audit --no-fund
├── npm run build (คอมไพล์ React 19 Frontend)
├── go mod tidy
├── wails3 generate syso (สร้าง Windows Manifest & Application Icon)
└── go build -tags production -trimpath -ldflags="-w -s -H windowsgui" -o <TempDir>/bin/G-Launcher.exe .
│
▼
3. สลับไฟล์ไบนารี (Atomic Swap & Rollback)
├── ตรวจสอบว่าไฟล์ไบนารีใหม่มีขนาด > 0 ไบต์
├── เปลี่ยนชื่อ: bin/G-Launcher.exe -> bin/G-Launcher.exe.old
├── ย้ายไฟล์ใหม่: <TempDir>/bin/G-Launcher.exe -> bin/G-Launcher.exe
├── หากล้มเหลว: ย้าย .old กลับมาทันที (Atomic Rollback)
└── หากสำเร็จ: ลบไฟล์ .old ทิ้ง
│
▼
4. ทำลายโฟลเดอร์ชั่วคราว 100% (Purge Temp)
└── บล็อก finally / defer os.RemoveAll ทำลายโฟลเดอร์ Temp ทิ้งทั้งหมด ห้ามทิ้งไฟล์ขยะ
```
---
## 4. Checklist สำหรับการตรวจสอบก่อน Commit / Push
ก่อนจะบันทึก Commit ใดๆ ในโปรเจกต์นี้ ให้ตรวจสอบ Checklist ต่อไปนี้ให้ครบ 100%:
1. [ ] อยู่บน Git branch **`Dev`** (`git branch --show-current` คืนค่า `Dev`)
2. [ ] ไม่มี URL, IP Address, หรือ Absolute Path (`C:\...`) ฮาร์ดโค้ดอยู่ในไฟล์ logic ใดๆ
3. [ ] ฝั่ง Go Backend: รัน `go vet ./...` ผ่าน 100% ไม่มีข้อผิดพลาด
4. [ ] ฝั่ง TypeScript/React: รัน `npm --prefix frontend run build` ผ่าน 100%
5. [ ] รัน `git status` แล้วไม่มีไฟล์ขยะ เช่น `tools/`, `node_modules/`, `bin/`, `temp/`, หรือ `*.old` ติดเข้ามาใน Staging Area
+27 -8
View File
@@ -21,14 +21,33 @@
## 📑 สารบัญเอกสารในโฟลเดอร์นี้
1. [**ARCHITECTURE.md**](./ARCHITECTURE.md)
* สถาปัตยกรรมโครงสร้างโปรเจกต์ Wails v3, Frontend React 19, และ Backend Services ทั้ง 5 ตัว
2. [**DEVELOPMENT_RULES.md**](./DEVELOPMENT_RULES.md)
* กฎ 6 ข้อในการพัฒนา และบทเรียนจาก Horoyoi-san & โปรเจกต์เดิม (Ananta / GaC-hkrpg-go)
3. [**UPDATER_SYSTEM.md**](./UPDATER_SYSTEM.md)
* กลไกและวงจรชีวิตของระบบ Auto-Updater และ Local Build (Temp Isolation, Rollback, Cleanup)
4. [**HISTORY_AND_LOGS.md**](./HISTORY_AND_LOGS.md)
* ไทม์ไลน์และประวัติการพัฒนาตั้งแต่เริ่มรวม 2 Repos จนถึงฟีเจอร์ปัจจุบัน
### 📌 เอกสารส่งต่อสถานะหลักและสัญญาทางเทคนิค (Core Handoff & Technical Contracts)
1. [**G-LAUNCHER-HANDOFF.md**](./G-LAUNCHER-HANDOFF.md)
* 🌟 **เอกสารหลักที่ต้องอ่านเป็นไฟล์แรกหลัง Compact:** สรุปสถานะงานแบบแยกชั้น (โค้ด/บิลด์/ดีพลอย/ยืนยันผล), กับดัก 5 ข้อที่ห้ามพลาด, และ Checklist ก่อน Commit
2. [**updater-temp-lifecycle.md**](./updater-temp-lifecycle.md)
* สัญญาทางเทคนิคของระบบอัปเดต 4 ขั้นตอน: การจัดการ Temp Workspace, การเลี่ยง Windows Process Lock, และระบบ Atomic Rollback
3. [**wails3-ipc-bindings-contract.md**](./wails3-ipc-bindings-contract.md)
* สัญญาการสื่อสาร Wails v3 IPC, ระบบ Type-Safe Bindings, และเหตุผลทางสถาปัตยกรรมที่ต้องทำ Go Backend ก่อน Frontend UI
4. [**diff-patching-engine.md**](./diff-patching-engine.md)
* กลไกการแพตช์ไฟล์ตัวเกมด้วย HPatchz (`.hdiff`), Zift (`.ziff`), การสกัดเครื่องมือจาก Embed Assets, และระบบ Safe Backup
5. [**git-runtime-mingit.md**](./git-runtime-mingit.md)
* สถาปัตยกรรม Portable MinGit: การตรวจจับและดาวน์โหลดอัตโนมัติโดยไม่ต้องใช้สิทธิ์ Administrator และการป้องกัน Terminal Hang
6. [**game-selection-persistence.md**](./game-selection-persistence.md)
* ระบบบันทึกพาธตัวเกมแบบทนทานต่อ Crash ด้วย Windows API `MoveFileEx` เพื่อป้องกันปัญหาไฟล์ JSON กลายเป็น 0 ไบต์
7. [**thai-localization-mod.md**](./thai-localization-mod.md)
* ระบบแปลภาษาไทย 2 ระดับ: Launcher UI (i18next) และ Game Modding (การแพตช์ไบต์ใน ExcelData พร้อมระบบกู้คืน)
8. [**upstream-merge-audit.md**](./upstream-merge-audit.md)
* ตารางแจกแจงที่มาของโค้ด (File Attribution Matrix) จากทั้ง Firefly Launcher และ Horoyoi-san
### 🏛️ เอกสารสถาปัตยกรรมและกฎการพัฒนาทั่วไป
9. [**ARCHITECTURE.md**](./ARCHITECTURE.md)
* สถาปัตยกรรมโครงสร้างโปรเจกต์ระดับสูง Wails v3, Frontend React 19, และ Backend Services ทั้ง 5 ตัว
10. [**DEVELOPMENT_RULES.md**](./DEVELOPMENT_RULES.md)
* กฎ 6 ข้อในการพัฒนา และบทเรียนจาก Horoyoi-san & โปรเจกต์เดิม (Ananta / GaC-hkrpg-go)
11. [**UPDATER_SYSTEM.md**](./UPDATER_SYSTEM.md)
* ภาพรวมและ Sequence Diagram ของระบบ Auto-Updater และ Local Build
12. [**HISTORY_AND_LOGS.md**](./HISTORY_AND_LOGS.md)
* ไทม์ไลน์และประวัติการพัฒนาตั้งแต่เริ่มรวม 2 Repos จนถึงปัจจุบัน
---
+63
View File
@@ -0,0 +1,63 @@
# 🧩 สัญญาทางเทคนิค: กลไกการแพตช์ไฟล์ตัวเกม (Diff & Patching Engine)
เอกสารนี้ระบุรายละเอียดการทำงานของระบบประมวลผลไฟล์ส่วนต่าง (Delta Patching) และการขยายแพ็กเกจข้อมูลเกมใน G-Launcher ซึ่งผสานเทคโนโลยีจาก Firefly Launcher และ Sunbringer เข้าด้วยกัน
---
## 1. ภาพรวมของเครื่องมือและฟอร์แมตที่รองรับ
| รูปแบบไฟล์ | เครื่องมือประมวลผล | ที่มาของโค้ด | หน้าที่และการทำงาน |
| :--- | :--- | :--- | :--- |
| **`.hdiff`** | `bin/hpatchz.exe` | Firefly / Hoyoverse | ใช้สำหรับอัปเดตไฟล์เกมแบบไบนารีเดลต้า (Byte-level Delta Patch) |
| **`.ziff`** | `bin/zift.exe` | Horoyoi-san (Sunbringer) | อัปเดตไฟล์เกมแบบบีบอัดพิเศษ Zift archive สำหรับม็อดและไฟล์แพตช์เฉพาะ |
| **`.zip` / `.7z`** | `bin/7za.exe` | 7-Zip Portable | คลายไฟล์ข้อมูลเกม แพตช์เสียง และแพ็กเกจเซิร์ฟเวอร์/พร็อกซี |
| **Protobuf Chunk** | `pkg/firefly/` | Firefly Engine | อ่านและถอดรหัส Hoyoverse manifest chunk สำหรับตรวจสอบความสมบูรณ์ของไฟล์ |
---
## 2. กลไกการสกัดเครื่องมือจาก Embed Assets (Tool Extraction Lifecycle)
เพื่อบรรลุเป้าหมาย **Zero-Dependency** ผู้ใช้ปลายทางไม่จำเป็นต้องมี 7-Zip หรือ HDiffz ติดตั้งในเครื่องล่วงหน้า:
1. ไบนารีของเครื่องมือทั้งหมดถูกฝัง (Embed) อยู่ในโค้ด Go ผ่าน `//go:embed assets/*` ใน [`main.go`](../main.go)
2. เมื่อ Launcher เริ่มทำงาน ฟังก์ชันตรวจสอบจะสแกนโฟลเดอร์ `bin/`:
* หากตรวจไม่พบ `bin/7za.exe`, `bin/hpatchz.exe` หรือ `bin/zift.exe`
* ระบบจะดึงไบต์จากหน่วยความจำออกมาเขียนเป็นไฟล์ executable ในโฟลเดอร์ `bin/` อัตโนมัติ พร้อมตั้งสิทธิ์การรัน
3. ไฟล์ที่ได้รับการดูแล:
* `bin/7za.exe`, `bin/7za.dll`, `bin/7zxa.dll`
* `bin/hpatchz.exe`
* `bin/zift.exe`
---
## 3. กฎความปลอดภัยของข้อมูลตัวเกม (Safe Backup & Atomic Rollback)
ไฟล์ตัวเกมมีขนาดใหญ่หลายสิบกิกะไบต์และเสียหายได้ง่าย หากการแพตช์ล้มเหลวระหว่างทาง ห้ามทิ้งไฟล์ให้อยู่ในสภาพพัง:
```
[เริ่มต้นแพตช์ไฟล์: StarRailBase.dll]
│
▼
1. สำรองไฟล์เดิม (Safe Backup)
└── คัดลอก StarRailBase.dll -> StarRailBase.dll.backup
│
▼
2. ดำเนินการแพตช์ด้วย HPatchz หรือ Zift
└── hpatchz.exe StarRailBase.dll patch.hdiff StarRailBase.dll.tmp
│
▼
3. ตรวจสอบความถูกต้อง (Checksum Verification)
├── หากผลลัพธ์ตรงกับ Checksum ที่กำหนด:
│ ├── สลับ StarRailBase.dll.tmp -> StarRailBase.dll
│ └── ลบไฟล์สำรอง StarRailBase.dll.backup ทิ้ง
│
└── หากเกิดข้อผิดพลาด / Checksum ไม่ตรง:
├── ลบไฟล์ชั่วคราว StarRailBase.dll.tmp ทิ้งทันที
├── Atomic Rollback: กู้คืนไฟล์จาก StarRailBase.dll.backup
└── ส่งข้อความแจ้งเตือนความล้มเหลวให้ผู้ใช้ทราบอย่างชัดเจน
```
---
## 4. สถานะการทดสอบและข้อจำกัด
* **ความพร้อมของระบบ:** โครงสร้าง Service และ Command Execution เขียนเสร็จสมบูรณ์ 100% ใน `internal/diff-service/`
* **ขอบเขตที่รอการยืนยัน:** การทดสอบด้วยไฟล์ `.ziff` และ `.hdiff` ขนาดใหญ่ของตัวเกมจริง ต้องรอการทดสอบร่วมกับไฟล์แพตช์จริงในสภาพแวดล้อมของผู้ใช้
+38
View File
@@ -0,0 +1,38 @@
# 🛡️ สัญญาทางเทคนิค: การบันทึกพาธเกมแบบทนทานต่อ 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:\` ในโค้ด
+54
View File
@@ -0,0 +1,54 @@
# 🧰 สัญญาทางเทคนิค: ระบบจัดการ Portable MinGit Runtime
เอกสารนี้อธิบายกลไกของ **Portable MinGit** ใน G-Launcher ซึ่งช่วยให้ระบบสามารถรันคำสั่ง Git (เช่น Git Clone, Git Fetch, Git Checkout) ได้บนคอมพิวเตอร์ของผู้ใช้ทั่วไป แม้ว่าในเครื่องจะไม่ได้ติดตั้งโปรแกรม Git หรือไม่มีสิทธิ์ Administrator ก็ตาม
---
## 1. ที่มาและปัญหาเดิม (Background & Problem Statement)
1. ผู้เล่นเกมทั่วไปส่วนใหญ่ไม่มีโปรแกรม Git สำหรับนักพัฒนาติดตั้งอยู่ในเครื่อง
2. ตัวติดตั้ง Git for Windows ปกติต้องการสิทธิ์ Administrator (UAC Prompt) ซึ่งสร้างความยุ่งยากให้แก่ผู้ใช้งาน
3. ตัวอัปเดต Launcher และระบบดาวน์โหลดเซิร์ฟเวอร์/พร็อกซี จำเป็นต้องใช้ Git ในการดึงข้อมูล
---
## 2. ลำดับการตรวจสอบและเตรียม Git Runtime (Discovery Order)
ใน [`internal/git-service/git_runtime.go`](../internal/git-service/git_runtime.go) ฟังก์ชัน `ensureGit()` ทำงานตามลำดับความสำคัญดังนี้:
```
[ร้องขอ Git Executable]
│
▼
1. ตรวจสอบ System PATH (exec.LookPath("git"))
├── พบ -> คืนพาธของ Git ในเครื่องทันที (เช่น C:\Program Files\Git\cmd\git.exe)
│
└── ไม่พบ -> เข้าสู่ขั้นตอนที่ 2
│
▼
2. ตรวจสอบโฟลเดอร์พกพาภายใน (tools/mingit/cmd/git.exe)
├── พบ -> นำพาธนี้ไปใช้งานทันที
│
└── ไม่พบ -> เข้าสู่ขั้นตอนที่ 3
│
▼
3. ดาวน์โหลด Portable MinGit x64 อัตโนมัติ
├── ดึงข้อมูล Release ล่าสุดจาก GitHub API:
│ https://api.github.com/repos/git-for-windows/git/releases/latest
├── กรองหาไฟล์แพ็กเกจ: MinGit-*-64-bit.zip
├── ดาวน์โหลดลงไฟล์ชั่วคราว os.CreateTemp
├── แตกไฟล์ Zip ลงโฟลเดอร์เป้าหมาย
└── คืนค่าพาธ git.exe พร้อมใช้งาน
```
---
## 3. การป้องกัน Terminal Freeze (Non-Interactive Terminal Execution)
เมื่อโปรแกรม Launcher หรือสคริปต์อัตโนมัติเรียกใช้คำสั่ง Git หาก Git ตรวจพบว่าต้องการรหัสผ่านหรือการยืนยันตัวตน มันจะพยายามเปิด Interactive TTY Prompt ซึ่งส่งผลให้โปรเซสของ Launcher **ค้างอย่างถาวร (Hang/Freeze)**:
### แนวทางป้องกันที่นำมาใช้:
1. **ตั้งค่าตัวแปรสภาพแวดล้อม:**
* ใน Go Backend: `cmd.Env = append(os.Environ(), "GIT_TERMINAL_PROMPT=0")`
* ใน PowerShell: `$env:GIT_TERMINAL_PROMPT = "0"`
2. **ผลลัพธ์:** หาก Git ต้องการการยืนยันตัวตนแต่ไม่สามารถทำได้ Git จะ Return Error ออกมาทันทีแทนที่จะค้าง ทำให้ระบบสามารถดักจับและส่ง Error ไปแจ้งเตือนบน UI ได้อย่างถูกต้อง
+24
View File
@@ -0,0 +1,24 @@
# 🇹🇭 สัญญาทางเทคนิค: ระบบแปลภาษาไทยและม็อดตัวเกม (Thai Localization & Game Modding)
เอกสารนี้ระบุรายละเอียดของระบบแปลภาษาไทย 2 ระดับใน G-Launcher:
1. **Launcher UI Localization:** การแปลภาษาบนหน้าจอและปุ่มควบคุมของตัว Launcher
2. **Game Asset Modding:** ระบบติดตั้งและถอนการติดตั้งแพตช์ภาษาไทยลงในไฟล์ข้อมูลของตัวเกม
---
## 1. การแปลภาษาบนหน้าต่าง Launcher (UI Localization)
* **เครื่องมือ:** `i18next` + `react-i18next`
* **ไฟล์ข้อมูลคำแปลภาษาไทย:** [`frontend/public/locales/th.json`](../frontend/public/locales/th.json)
* **การเปลี่ยนภาษาแบบทันที:** คอมโพเนนต์ [`LanguageSwitcher`](../frontend/src/components/languageSwitcher/) ช่วยให้ผู้ใช้สามารถสลับระหว่างภาษาไทย (`th`), อังกฤษ (`en`), จีน (`zh`), ญี่ปุ่น (`ja`), เกาหลี (`ko`), และเวียดนาม (`vi`) ได้ทันทีโดยไม่ต้องรีสตาร์ตโปรแกรม
---
## 2. ระบบติดตั้งม็อดภาษาไทยลงในตัวเกม (Game Asset Modding)
ใน [`internal/language-service/thai-patch.go`](../internal/language-service/thai-patch.go) บริการ `LanguageService` จัดการการแก้ไขไฟล์ไบนารี `ExcelData` ของเกม:
### กฎความปลอดภัยในการแก้ไขไฟล์เกม (Mandatory Safety Rules):
1. **การสำรองไฟล์เดิม (Safe Backup):** ก่อนจะเริ่มเขียนหรือแก้ไขไบต์ในไฟล์ข้อมูลเกม ระบบจะทำการคัดลอกไฟล์ต้นฉบับเก็บไว้เป็นนามสกุล `.backup` เสมอ
2. **การกู้คืนอัตโนมัติ (Atomic Restore):** หากการเขียนไบต์ล้มเหลว หรือผู้ใช้กดปุ่ม "ถอนการติดตั้งม็อด" ระบบจะนำไฟล์ `.backup` กลับมาทับไฟล์เดิมทันที ทำให้ไฟล์ตัวเกมกลับสู่สถานะของแท้ 100%
3. **การตรวจสอบสถานะ (Status Probe):** ตรวจสอบว่ามีไฟล์ `.backup` หรือมาร์กเกอร์ของม็อดอยู่หรือไม่ เพื่อแสดงสถานะบน UI ว่าเกมนี้ลงม็อดภาษาไทยแล้วหรือยัง
+74
View File
@@ -0,0 +1,74 @@
# 🔄 สัญญาทางเทคนิค: วงจรชีวิตของระบบอัปเดต (Updater Temp Lifecycle Contract)
เอกสารนี้ระบุข้อตกลงและสัญญาทางเทคนิค (Contract) สำหรับระบบอัปเดตและบิลด์ในเครื่องของ G-Launcher ซึ่งครอบคลุมทั้งสคริปต์ PowerShell ([`scripts/bootstrap.ps1`](../scripts/bootstrap.ps1)) และบริการ Go Backend ([`internal/git-service/launcher.go`](../internal/git-service/launcher.go))
---
## 1. วัตถุประสงค์และข้อจำกัดของระบบปฏิบัติการ (Operating System Constraints)
### ปัญหาข้อจำกัดของ Windows:
1. **Windows Executable Locking:** เมื่อโปรเซส `.exe` กำลังทำงานอยู่ ระบบปฏิบัติการจะเปิดแฮนเดิลไฟล์ด้วยการล็อกแบบแชร์การอ่าน (`FILE_SHARE_READ`) แต่ไม่อนุญาตให้เขียน (`GENERIC_WRITE`) หรือลบทิ้ง (`DELETE`) โดยตรง
2. **ข้อยกเว้นการเปลี่ยนชื่อ (Rename Privilege):** บน Windows อนุญาตให้ **เปลี่ยนชื่อ (Rename/Move)** ไฟล์ executable ที่กำลังทำงานอยู่ได้ ตราบใดที่ยังอยู่บนโวลุม (Volume/Drive) เดียวกัน
3. **การหลีกเลี่ยง Build In-Place:** การรัน `git pull` หรือ `go build` ทับโฟลเดอร์หลักของ Launcher ขณะที่ตัว Launcher รันอยู่ จะทำให้เกิด Exception `Access is denied` ทันที และอาจทำให้โฟลเดอร์ซอร์สโค้ดค้างอยู่ในสถานะไม่สมบูรณ์
---
## 2. ขั้นตอนทั้ง 4 ของวงจรชีวิต (The 4 Lifecycle Phases)
### Phase 1: การจัดเตรียมพื้นที่ชั่วคราวและการดาวน์โหลด (Download to Temp)
* **PowerShell:**
* โฟลเดอร์เป้าหมาย: `$tempBuildDir = Join-Path $rootDir "temp\build_workspace"`
* หากมีโฟลเดอร์ตกค้างจากรอบก่อน ให้สั่งลบทิ้งก่อนสร้างใหม่เสมอ
* สั่ง `git clone --depth 1 --branch Dev https://gaytea.cod-algieba.ts.net/GaCy/G-Launcher.git $tempBuildDir`
* หากการ Clone ผ่านเน็ตเวิร์กล้มเหลว (เช่น ทำงานแบบออฟไลน์) สคริปต์จะสลับไป Clone จากโฟลเดอร์ท้องถิ่น (`$rootDir`) เข้าสู่ `$tempBuildDir` แทน
* **Go Backend:**
* ใช้ `tempDir, err := os.MkdirTemp("", "g-launcher-build-*")`
* สั่งงาน Git ผ่านฟังก์ชัน `ensureGit()` เพื่อรับประกันว่ามี Portable MinGit ทำงานได้โดยไม่ต้องพึ่งสิทธิ์ Administrator
### Phase 2: การคอมไพล์แบบแยกส่วนในโฟลเดอร์ชั่วคราว (Isolated Build)
* สวิตช์ Working Directory เข้าสู่โฟลเดอร์ชั่วคราว (`Push-Location $tempBuildDir` หรือ `cmd.Dir = tempDir`)
* ลำดับการคอมไพล์:
1. `npm --prefix frontend install --no-audit --no-fund` (ติดตั้ง dependencies ของ React 19)
2. `npm --prefix frontend run build` (คอมไพล์ assets ผ่าน Vite 8 ได้ผลลัพธ์ลง `frontend/dist/`)
3. `go mod tidy` (จัดระเบียบ Go modules)
4. `wails3 generate syso` (สร้าง Windows PE Resource, Manifest, DPI awareness, และ Icon)
5. `go build -tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui" -o bin/G-Launcher.exe .`
* ตรวจสอบว่าไฟล์ไบนารีผลลัพธ์ถูกสร้างขึ้นจริง และมีขนาดมากกว่า 0 ไบต์
* สลับกลับสู่ Working Directory เดิม (`Pop-Location`) ก่อนเริ่มขั้นตอนถัดไป
### Phase 3: การสลับไฟล์ไบนารีอย่างปลอดภัยและการ Rollback (Atomic Swap & Safe Rollback)
* หากไฟล์เป้าหมาย `bin/G-Launcher.exe` มีอยู่เดิม:
1. เปลี่ยนชื่อไฟล์เดิมเป็น `bin/G-Launcher.exe.old`
2. ย้ายไฟล์ใหม่จากโฟลเดอร์ Temp มาวางที่ `bin/G-Launcher.exe`
3. หากการย้ายไฟล์ล้มเหลว (เกิด Exception):
* **Rollback ทันที:** ย้าย `bin/G-Launcher.exe.old` กลับมาเป็น `bin/G-Launcher.exe` เพื่อให้ผู้ใช้ยังสามารถเปิดโปรแกรมเดิมได้
* แจ้งข้อผิดพลาดและยุติการทำงาน
4. หากการย้ายไฟล์สำเร็จ:
* ลบไฟล์ `bin/G-Launcher.exe.old` (หากโปรแกรมเดิมกำลังรันอยู่และยังลบไม่ได้ ไฟล์นี้จะถูกเพิกเฉยและรอการลบในรอบถัดไป)
* ในฝั่ง Go Backend ใช้ไลบรารี `github.com/minio/selfupdate`:
* ฟังก์ชัน `selfupdate.Apply(newBinaryReader, selfupdate.Options{})` ดำเนินการ Rename & Swap แบบ Atomic ในระดับ Native Windows API
### Phase 4: การทำลายโฟลเดอร์ชั่วคราว (Guaranteed Temp Purge)
* **PowerShell:**
* ครอบกระบวนการทั้งหมดด้วยบล็อก `try { ... } finally { ... }`
* ในบล็อก `finally`:
```powershell
Set-Location $rootDir
if (Test-Path $tempBuildDir) {
Remove-Item -LiteralPath $tempBuildDir -Recurse -Force -ErrorAction SilentlyContinue
}
```
* การันตีว่าโฟลเดอร์ Temp จะถูกลบออก 100% เสมอ ไม่ว่าการบิลด์จะสำเร็จหรือเกิดข้อผิดพลาด
* **Go Backend:**
* ใช้คำสั่ง `defer os.RemoveAll(tempDir)` ทันทีหลังสร้าง `os.MkdirTemp` สำเร็จ
---
## 3. หลักฐานการตรวจสอบจริง (Empirical Verification Log)
ผลการทดสอบสคริปต์จริงในสภาพแวดล้อม Windows 64-bit (Task ID: `task-607`):
* โฟลเดอร์ชั่วคราว: `C:\Users\Phitchayut\Desktop\G Launcher\temp\build_workspace`
* เวลาในการดาวน์โหลดและแตกแพ็กเกจ Frontend: 21 วินาที
* เวลาในการคอมไพล์ Vite Frontend: 751 มิลลิวินาที
* ขนาดไฟล์ Executable ผลลัพธ์: **28,677,632 ไบต์ (27.35 MB)**
* ผลการตรวจสอบการล้างขยะ: คำสั่ง `Test-Path .\temp\build_workspace` คืนค่า **`False`** (โฟลเดอร์ชั่วคราวถูกลบทิ้งหมดจด ไร้ขยะตกค้าง)
+29
View File
@@ -0,0 +1,29 @@
# 🔍 ผลการตรวจสอบการผสานต้นน้ำ (Upstream Merge & Provenance Audit)
เอกสารนี้บันทึกที่มา (Provenance) ของโค้ดทุกส่วนใน G-Launcher โดยแจกแจงอย่างชัดเจนว่าฟีเจอร์ใดนำมาจาก `Firefly-Shelter/Firefly_Launcher` หรือ `horoyoi-san/game-Launcher`
---
## 1. ตารางแจกแจงที่มาของไฟล์และฟังก์ชัน (File Attribution Matrix)
| ไฟล์ / แพ็กเกจใน G-Launcher | โครงการต้นแบบ | เหตุผลทางวิศวกรรมและสิ่งที่ปรับปรุง |
| :--- | :--- | :--- |
| `frontend/src/` (UI Pages & Components) | **Firefly Launcher** | ดีไซน์ทันสมัย เรียบหรู รองรับ DaisyUI 5 และ TailwindCSS v4 |
| `internal/git-service/git_runtime.go` | **Horoyoi-san** | นำระบบดาวน์โหลด Portable MinGit x64 อัตโนมัติมาใช้ เพื่อรองรับ Zero-Dependency |
| `internal/fs-service/game-selection.go` | **Horoyoi-san** | นำระบบ Atomic Write ด้วย Windows API `MoveFileEx` มาใช้เพื่อป้องกันไฟล์คอนฟิกเสียหาย |
| `internal/diff-service/ziff.go` | **Horoyoi-san** | นำ Wrapper สำหรับเครื่องมือ `zift.exe` มาใช้รองรับไฟล์แพตช์นามสกุล `.ziff` |
| `internal/language-service/thai-patch.go`| **Horoyoi-san** | นำเอ็นจินแก้ไขไฟล์ไบนารี `ExcelData` พร้อมระบบสำรอง `.backup` มาใช้สำหรับม็อดภาษาไทย |
| `scripts/launcher-release.mjs` | **Horoyoi-san** | นำสคริปต์คำนวณเวอร์ชัน SemVer และสร้าง `latest.json` มาใช้ใน CI/CD Release Pipeline |
| `frontend/public/locales/th.json` | **G-Launcher (GaCy)** | เขียนคำแปลภาษาไทยฉบับสมบูรณ์สำหรับทุกหน้าจอ ปุ่ม และเมนูของ Launcher |
| `scripts/bootstrap.ps1` | **G-Launcher (GaCy)** | พัฒนาระบบ Auto-Updater & Local Build ที่ทำงานแบบ **Temp Isolation + Rollback + Purge Temp** |
| `update-and-build.bat` | **G-Launcher (GaCy)** | พัฒนาสคริปต์คลิกเดียวสำหรับผู้ใช้ทั่วไปเพื่ออัปเดตและคอมไพล์โดยไม่ต้องตั้งค่าใดๆ |
| `internal/git-service/launcher.go` | **G-Launcher (GaCy)** | ผสานระบบตรวจสอบผ่าน Manifest SHA-256 และระบบคอมไพล์จากซอร์สโค้ดใน Temp เข้าด้วยกัน |
---
## 2. การจัดการ Naming และ Module Rebranding
เพื่อปฏิบัติตามคำแนะนำของ Horoyoi-san (*"ส่วนชื่อที่เป็น sunbringer หรือชื่อผมค่อยไปเปลี่ยนทีหลังนะ"*):
1. **Module Name:** เปลี่ยนชื่อ Go Module หลักเป็น `g-launcher` ใน `go.mod`
2. **User-Facing Branding:** เปลี่ยนชื่อหน้าต่าง, Title, ข้อความใน UI, และ Metadata ของ Windows Application Manifest เป็น **G-Launcher**
3. **Internal Identifiers:** อนุรักษ์ชื่อโครงสร้างข้อมูลและโปรโตคอลภายในที่จำเป็นต่อการเชื่อมต่อกับระบบเดิมไว้ เพื่อไม่ให้กระทบต่อ Wails Bindings และ Protobuf Serialization
+81
View File
@@ -0,0 +1,81 @@
# 🔌 สัญญาทางเทคนิค: Wails v3 IPC & Type-Safe Bindings Architecture
เอกสารนี้อธิบายกลไกการสื่อสารข้ามเลเยอร์ (IPC Bridge) ระหว่าง **Go Core Services** และ **React 19 Frontend** ในสถาปัตยกรรม Wails v3 Alpha ของ G-Launcher
---
## 1. ลำดับการลงทะเบียนและส่งผ่านข้อมูล (IPC Gateway Flow)
```mermaid
sequenceDiagram
autonumber
participant GoService as Go Service (internal/*-service)
participant MainGo as main.go (RegisterService)
participant WailsCLI as wails3 generate bindings
participant TSBindings as frontend/bindings/@bindings/...
participant ReactUI as React Component (frontend/src/...)
GoService->>MainGo: ประกาศ Method พร้อม Input/Output Type ชัดเจน
MainGo->>MainGo: app.RegisterService(application.NewService(serviceInstance))
MainGo-->>WailsCLI: Wails CLI ทำการสแกน Abstract Syntax Tree (AST) ของ Go
WailsCLI->>TSBindings: สร้างไฟล์ TypeScript Definition (.d.ts) และ JS Wrapper
TSBindings->>ReactUI: นำเข้า (Import) มาใช้ใน React ด้วย Type Safety 100%
ReactUI->>GoService: เรียกใช้แบบ Async Promise ผ่าน Native Webview IPC Bridge
GoService-->>ReactUI: คืนค่า Array Result [value1, value2, ...] ตามธรรมเนียม Wails v3
```
---
## 2. ทำไมต้องยึดกฎ "System-First Architecture" อย่างเคร่งครัด?
1. **Static AST Analysis:** Wails v3 สร้าง Bindings โดยการวิเคราะห์โค้ด Go แบบ Static AST หากแก้ไข UI ให้เรียกฟังก์ชันหรือส่งพารามิเตอร์ที่ Go Backend ยังไม่มี โค้ดฝั่ง Frontend จะเกิด Type Error ทันทีตอนรัน `tsc`
2. **Runtime IPC Exception:** หากหลุดจากการตรวจสอบของ TypeScript (เช่น ใช้ `any` หรือเรียกแบบไดนามิก) เมื่อ Webview ส่ง IPC Message ผ่าน MessageHandler ของ Windows WebView2 ไปยัง Go Backend ที่ไม่มีตัวรับ จะทำให้เกิด `Unhandled IPC Error` ส่งผลให้หน้าต่างโปรแกรมค้าง จอดำ หรือเปิดมาเป็นหน้าจอสีขาวสนิท (White Screen of Death)
3. **แนวปฏิบัติที่ถูกต้อง:**
* ขั้นที่ 1: เพิ่ม Struct หรือ Method ใน Go Backend ก่อน
* ขั้นที่ 2: รัน `go vet ./...` ให้มั่นใจว่า Backend ไม่มีข้อผิดพลาด
* ขั้นที่ 3: สั่งรัน `wails3 generate bindings` เพื่อซิงก์ TypeScript Bindings ลง `frontend/bindings/`
* ขั้นที่ 4: ตรวจสอบ Interface ใน `frontend/bindings/`
* ขั้นที่ 5: แก้ไข UI และ State Store ใน Frontend ให้สอดคล้องกัน
---
## 3. รายการบริการและผัง Bindings ทั้ง 5 โมดูล
### 1. `AppService` (`@bindings/g-launcher/internal/app-service`)
* `CloseAppAfterTimeout(seconds: number): Promise<void>`
* `GetCurrentLauncherVersion(): Promise<[boolean, string]>`
* `Minimize(): Promise<void>`
* `ToggleMaximize(): Promise<void>`
* `Close(): Promise<void>`
### 2. `FSService` (`@bindings/g-launcher/internal/fs-service`)
* `FileExists(path: string): Promise<boolean>`
* `OpenFileDialog(title: string, filter: string): Promise<string>`
* `SaveGameSelection(path: string): Promise<boolean>`
* `GetSavedGameSelection(): Promise<[boolean, string]>`
* `StartGameProcess(gamePath: string): Promise<[boolean, string]>`
### 3. `GitService` (`@bindings/g-launcher/internal/git-service`)
* `GetLatestLauncherVersion(): Promise<[boolean, string, string]>`
* `UpdateLauncherProgress(version: string): Promise<[boolean, string]>`
* `BuildAndUpdateFromSource(branch: string): Promise<[boolean, string]>`
* `GetLatestProxyVersion(): Promise<[boolean, string, string]>`
* `DownloadProxy(version: string): Promise<[boolean, string]>`
* `GetLatestServerVersion(): Promise<[boolean, string, string]>`
* `DownloadServer(version: string): Promise<[boolean, string]>`
### 4. `DiffService` (`@bindings/g-launcher/internal/diff-service`)
* `ApplyHDiffPatch(targetDir: string, diffFilePath: string): Promise<[boolean, string]>`
* `ApplyZiffPatch(targetDir: string, ziffFilePath: string): Promise<[boolean, string]>`
* `VerifyChunkChecksum(filePath: string, expectedHash: string): Promise<boolean>`
### 5. `LanguageService` (`@bindings/g-launcher/internal/language-service`)
* `InstallThaiPatch(gameDir: string): Promise<[boolean, string]>`
* `UninstallThaiPatch(gameDir: string): Promise<[boolean, string]>`
* `CheckThaiPatchStatus(gameDir: string): Promise<[boolean, boolean]>`
---
## 4. ผลการตรวจสอบความสมบูรณ์ (Verification Status)
* คำสั่ง `wails3 generate bindings` สแกนพบ: **470 Packages, 5 Services, 41 Methods, 0 Errors**
* โค้ดฝั่ง React คอมไพล์ผ่าน TypeScript Check (`tsc`) และ Vite Build ได้อย่างสมบูรณ์แบบ