Files
GaCy-GO/README.md
T

215 lines
22 KiB
Markdown
Raw Normal View History

# GaC hkrpg GO
เซิร์ฟเวอร์จำลอง Honkai: Star Rail ภาษา Go พอร์ตจาก `GaC-hkrpg-ps` และอ้างอิงการทำงานจาก [PearlSR](https://git.xeondev.com/HonkaiSlopRail/pearl-sr) ประกอบด้วย game server, SDK/dispatch server และ REST API สำหรับ GaC-Srtool
โปรเจกต์อยู่ระหว่างพัฒนา โดยกำลังตรวจการใช้งานกับ Client **4.6.53 OS** ตารางคำสั่งและ handler ที่แก้ล่าสุดอ้างอิง PearlSR commit `005d2c12db4781071f4b5b68e8f364587886a710` รายละเอียดอยู่ใน [บันทึกอัปเดต protocol](docs/protocol-update.md) การตรงกันของ schema ไม่ได้ยืนยันว่าเกมทุกระบบทำงานครบ
## เริ่มใช้งานบน Windows
1. ติดตั้ง **Go 1.27.0 ขึ้นไป** ตาม `go.mod` และตรวจด้วย `go version`
2. เตรียม Client, launcher/proxy และการ redirect dispatch ให้เชื่อมต่อเซิร์ฟเวอร์ที่กำหนดใน `server.json`
3. เก็บไฟล์ข้อมูลและโฟลเดอร์ `resources` ไว้ใน root ของโปรเจกต์ และตั้งค่า launcher ตามหัวข้อ config ด้านล่าง
4. เปิด `run.bat` แล้วเลือกเมนูที่ต้องการ
| เมนู | การทำงาน |
| --- | --- |
| `1` หรือ Enter | Build ทั้งสองเซิร์ฟเวอร์ แล้วเปิดเซิร์ฟเวอร์และเกม |
| `2` | เปิดทั้งสองเซิร์ฟเวอร์จาก `.exe` ที่มีอยู่ |
| `3` | เปิดเฉพาะ SDK server |
| `4` | เปิดเฉพาะ game server |
| `5` | เปิดทั้งสองเซิร์ฟเวอร์จาก `.exe` ที่มีอยู่ และเรียก Gay Proxy |
| `6` | Build ทั้งสอง `.exe` อย่างเดียว |
| `7` | ออก |
| `8` หรือ `stop` | หยุดเซิร์ฟเวอร์ของโปรเจกต์นี้ |
เมนู 1 และ 6 หยุดเมื่อ build ไม่ผ่าน ส่วนเมนู 2–5 ใช้ binary ที่มีอยู่ หลังแก้ซอร์สจึงต้อง build ใหม่ก่อนใช้เมนูเหล่านั้น
`run.bat` เรียก `run.ps1` ผ่าน PowerShell โดยอ่าน path เกม/Proxy จาก config ไม่มีการเดา Desktop, ไดรฟ์ หรือชื่อโฟลเดอร์ตามเวอร์ชัน ต้องตั้ง `launcher.client_path` เป็นไฟล์ launcher/เกมที่จะเปิด และ `launcher.proxy_path` เป็นไฟล์ Proxy ที่ต้องการ ถ้าเว้นว่างจะเปิดเซิร์ฟเวอร์และแสดงวิธีตั้งค่า
SDK และ game server เปิดหน้าต่างคอนโซลแยกกันให้เห็น log โดยตรง หลังทำเมนูที่เลือกเสร็จ หน้าต่าง `run.bat` จะปิดเองใน 5 วินาที ส่วนหน้าต่างเซิร์ฟเวอร์ยังเปิดอยู่ ใช้ `run.bat stop` เพื่อหยุด หรือปิดหน้าต่างเซิร์ฟเวอร์ที่ต้องการ สคริปต์หยุดเฉพาะ process ที่ path executable ตรงกับ root นี้ ก่อนเริ่มใหม่หรือแทนที่ binary ที่ build สำเร็จ การเรียกด้วย argument เช่น `run.bat build` จะคืนค่าทันทีเมื่อทำงานเสร็จโดยไม่รอ 5 วินาที
## Config และกฎห้าม hardcode
`AGENTS.md` กำหนดให้ค่าที่เปลี่ยนตามเครื่อง/deployment/เวอร์ชันต้องมาจาก config, environment หรือ resource ห้ามฝัง path, IP, port หรือ fallback เฉพาะเครื่องใน source และ startup scripts
ลำดับความสำคัญ: **environment > local config > config หลัก**
- `server.json`: ค่าเครือข่ายและเวอร์ชันที่แชร์กันระหว่าง launcher, game server และ SDK server
- `server.local.json`: override เฉพาะเครื่อง ไฟล์นี้ถูก ignore โดย Git คัดลอก `server.local.example.json` แล้วใส่ path ของเครื่องได้
- `GAC_CONFIG`: เลือกไฟล์หลักอื่น โดย local override ใช้ชื่อเดียวกันลงท้าย `.local.json`
- path แบบ relative ใน launcher อ้างอิง root ของโปรเจกต์
| ค่าใน config | Environment override | ใช้สำหรับ |
| --- | --- | --- |
| `client_version` | `GAC_CLIENT_VERSION` | เวอร์ชันที่แสดงใน log/API |
| `game_host`, `game_port` | `GAC_GAME_HOST`, `GAC_GAME_PORT` | ที่อยู่ bind ของ game server |
| `sdk_host`, `sdk_port` | `GAC_SDK_HOST`, `GAC_SDK_PORT` | ที่อยู่ bind ของ SDK server |
| `public_game_host` | `GAC_PUBLIC_GAME_HOST` | ที่อยู่ game server ที่ gateway แจ้ง Client |
| `public_sdk_url` | `GAC_PUBLIC_SDK_URL` | Base URL ที่ dispatch แจ้ง Client |
| `launcher.client_path` | `GAC_CLIENT_PATH` | ไฟล์ launcher/เกมที่จะเปิด |
| `launcher.proxy_path` | `GAC_PROXY_PATH` | ไฟล์ Proxy ที่จะเปิด |
| `launcher.go_command` | `GAC_GO_COMMAND` | คำสั่ง Go จาก PATH หรือ path ที่กำหนด |
เมื่อเปลี่ยนเครือข่ายให้ตั้งทั้ง bind และค่าที่ประกาศให้ Client เข้าถึงได้ โดยเฉพาะ port ใน `public_sdk_url` เมื่อ SDK รับการเชื่อมต่อโดยตรง ค่าเหล่านี้มีค่าเริ่มต้นอยู่ในไฟล์ config และไม่มี fallback เครือข่ายในโค้ด ต้องรีสตาร์ตเซิร์ฟเวอร์หลังเปลี่ยน config การเปลี่ยน `client_version` ไม่ได้แปลง protocol หรือทรัพยากรของเกมให้อัตโนมัติ
ตรวจ config โดยไม่เปิดเกมหรือเซิร์ฟเวอร์:
```powershell
.\run.bat check
```
## ทำไมมี executable สองตัว
| ไฟล์ | หน้าที่ | พอร์ต |
| --- | --- | --- |
| `gameserver-go.exe` | รับการเชื่อมต่อเกมผ่าน KCP และจัดการผู้เล่น ฉาก และ battle | UDP ตาม `game_port` |
| `sdkserver-go.exe` | Dispatch, login, ข้อมูล hotfix และ REST API | HTTP ตาม `sdk_port` |
การเปิดระบบครบต้องรันทั้งสองตัว `.exe` ที่ build เสร็จจะอยู่ใน root ของโปรเจกต์ ให้เปิดจาก root เพื่อให้เซิร์ฟเวอร์หาไฟล์ข้อมูลและบันทึก log ได้ถูกตำแหน่ง
## Build และรันเอง
รันคำสั่งจาก root ของโปรเจกต์:
```powershell
go build -o gameserver-go.exe ./cmd/gameserver
go build -o sdkserver-go.exe ./cmd/sdkserver
```
เปิดคนละ terminal:
```powershell
.\sdkserver-go.exe
```
```powershell
.\gameserver-go.exe
```
ซอร์สมีไฟล์ protobuf ที่ generate แล้ว การ build ปกติไม่ต้องใช้ `protoc` หากแก้ schema จึงต้องติดตั้ง `protoc` และ `protoc-gen-go` เพื่อ generate ใหม่
สำหรับนักพัฒนาที่ต้องการรันชุดทดสอบ:
```powershell
go test ./...
```
ผลทดสอบฝั่ง Go และการ build สำเร็จไม่ได้ยืนยันว่า Client โหลดฉากหรือเข้า battle สำเร็จ ต้องตรวจในเกมและอ่าน `Player.log` ประกอบด้วย
## ไฟล์ข้อมูล
| ไฟล์หรือโฟลเดอร์ | ใช้สำหรับ |
| --- | --- |
| `freesr-data.json` | ตัวละคร, lightcone, relic และ `battle_config` |
| `persistent` | ทีม, ตำแหน่ง, ฉาก และค่าผู้เล่นที่บันทึกไว้ |
| `res.json` | ข้อมูลฉากหลักในรูปแบบที่ Go loader ใช้ |
| `resources/` | ข้อมูลฉากและตารางประกอบ เช่น MapEntrance, MazePlane, Anchor และ StageConfig |
| `teleports.json` | ตำแหน่ง teleport แยกตาม floor |
| `challenge_data.json` | ข้อมูล challenge |
| `mission_unlocks.json` | ข้อมูลภารกิจและการปลดล็อก |
| `hotfix.json`, `versions.json` | ข้อมูลเวอร์ชันและทรัพยากร Client สำหรับ SDK server |
| `scripts/` | Lua ที่ส่งให้ Client ผ่าน heartbeat |
สำรอง `freesr-data.json` และ `persistent` ก่อนเปลี่ยนชุดข้อมูล `res.json` ใน root กับ `resources/res.json` มีโครงสร้างต่างกันและ loader ใช้ร่วมกัน จึงควรเก็บไว้ตามตำแหน่งเดิม
**Calyx ใช้ `battle_config` ใน `freesr-data.json` เป็นข้อมูลจำลองการต่อสู้** จึงอาจได้ StageID และมอนสเตอร์ต่างจากดอกไม้ที่กดในเกม
## REST API / GaC-Srtool
เมื่อ SDK server ทำงาน เปิด URL ที่ตั้งใน `public_sdk_url` เพื่อดูรายการ endpoint หน้า root และ `/dashboard` ตอบข้อมูล JSON ของ API gateway
| Method | Endpoint | หน้าที่ |
| --- | --- | --- |
| GET | `/api/status` | อ่านสถานะและข้อมูลผู้เล่น |
| GET, POST | `/api/freesr` | อ่านหรืออัปเดต FreeSR data |
| GET, POST | `/api/freesr/avatars` | อ่านหรืออัปเดตข้อมูลตัวละคร |
| GET, POST | `/api/persistent` | อ่านหรืออัปเดตข้อมูล persistent |
| POST | `/api/exrank/toggle` | สลับการปลดล็อก EX rank |
| POST | `/api/avatar/rank` | เปลี่ยน rank ตัวละคร |
| POST | `/api/avatar/max_all` | ปรับข้อมูลตัวละครตามการทำงานของ handler |
| POST | `/api/teleport` | อัปเดตข้อมูลจุดหมาย teleport |
รูปแบบ request และเงื่อนไขการอัปเดตอยู่ใน `internal/sdkserver/api.go` การอัปเดตข้อมูลผ่าน API ยังต้องตรวจผลการโหลดข้อมูลของ Client ด้วย
## สถานะและปัญหาที่กำลังตรวจ
มี handler สำหรับ login, ทีม, ตัวละคร, ไอเทม, ฉาก, teleport, ภารกิจ, Calyx และ challenge แต่ความครบของ handler ไม่ได้หมายถึงรองรับทุกกรณีใน Client
| รายการ | สถานะ |
| --- | --- |
| Error 2000 ตอน login | แก้ `GetCurBattleInfo` ให้ตอบสำเร็จพร้อมข้อมูลว่างเมื่อไม่มี battle; รอยืนยันในเกม |
| Calyx | ผู้ใช้ยืนยันว่าเข้า Battle ได้แล้ว 17 ต.ค. หลังแก้เส้นทาง BattleInfo |
| ตีมอนแล้วค้างหน้า Weakness | ผู้ใช้ยืนยัน Stagnant Shadow ที่เรียกมอนออกมาให้ตีเข้าสู้ได้แล้ว 17 ต.ค.; log มี `PVEBattleResult` ส่วนมอนทั่วไปยังไม่ได้ยืนยันแยก |
| เปิดหน้าตัวละครแล้วค้าง | ผู้ใช้ยืนยันว่าหายหลังเปิดเกมใหม่; ไม่พบ PlayerBoard/Inventory error ใน log รอบใหม่ |
| วาร์ปแมพใหม่ | ปรับลำดับ response/notify และข้อมูล scene ตาม upstream; ยังต้องยืนยันปลายทางในเกม |
| `SceneCastSkill` | ใช้รายการ monster entity ที่ server สร้างเพื่อตรวจเป้าหมายก่อนส่ง battle |
ข้อมูลล่าสุดที่ตรวจในซอร์สและเอกสาร: **17 ตุลาคม 2026**
## เก็บข้อมูลเมื่อพบปัญหา
| ไฟล์ | ข้อมูลที่ช่วยวิเคราะห์ |
| --- | --- |
| `gameserver.log` | คำขอและแพ็กเก็ตตอบกลับ |
| `server_debug.log` | รายละเอียด battle, scene และ teleport |
| `battle_last.json` | Payload battle ล่าสุดที่สร้างสำหรับ Calyx หรือการตีมอน |
| `battle_last_response.bin`, `battle_last.bin` | ไบต์ response ที่ส่งจริง และ nested battle_info ที่ตัดจาก response นั้น |
| `battle_last_capture.json`, `battle_diagnostics/` | CmdID, เวลา, SHA-256 และ snapshot ของแต่ละรอบ |
| `Player.log` ของ Client | Exception และจุดที่ Client โหลดข้อมูลไม่สำเร็จ |
ตำแหน่ง `Player.log` บน Windows สำหรับ Client ที่ใช้ในงานนี้:
```text
%USERPROFILE%\AppData\LocalLow\Cognosphere\Star Rail\Player.log
```
เมื่อรายงานปัญหาให้ระบุเวอร์ชัน Client, เวลาที่เกิด, การกระทำก่อนค้าง และรหัส Cocoon/Entry/Teleport ถ้ามี พร้อม log ช่วงเดียวกันทั้ง server และ Client ข้อความ `sent packet` ยืนยันเพียงว่า server ส่งแพ็กเก็ตแล้ว ส่วนการโหลดสำเร็จต้องดูฝั่ง Client
สำหรับการตรวจ battle ทีละส่วน ดู [บันทึกเทียบ upstream](docs/battle-investigation.md) ค่า `battle_diagnostics.client_battle_type` ใน local config เปิด probe ที่อ่าน payload ด้วย protobuf parser ของ Client และเขียน `[GAC_BATTLE_WIRE]` ลง Player.log ชื่อ class ต้องอ้างอิง stack trace ของ Client รุ่นนั้น ตั้งค่าว่างเพื่อปิด probe
ประวัติรอบ 16 ต.ค. พบ main affix ผิดใน inventory ชุดเดิมและแก้ข้อมูลไปแล้ว ผลนั้นไม่ใช่หลักฐานว่า inventory ที่นำเข้าภายหลังหรือการเข้า Battle ปัจจุบันผ่าน ดูผลแต่ละรอบในบันทึกตรวจสอบ
### การแก้ Battle รอบ 17 ตุลาคม 2026
- `SceneCastSkill` อ่านทั้ง hit targets, assist IDs และ assist groups และตอบ `MonsterBattleType=TRIGGER_BATTLE` ตาม enum ของต้นฉบับ; ค่าเริ่มต้นศูนย์หมายถึง `NONE`
- โหลดธาตุตัวละครจาก `resources/AvatarConfig.json` เพิ่มเติม เพราะ `avatarConfigs` ใน `res.json` อาจว่าง
- กฎบัฟเฉพาะตัวละคร, global passive, entry attack และ invasion อยู่ใน `resources/BattleRules.json` พร้อม upstream revision ต้องนำไฟล์นี้ไปด้วยเมื่อแจก binary; ไม่มีการฝัง ID ของกฎเหล่านี้เป็น fallback ในตัว executable
- Battle SP แปลงจากอัตราส่วนในข้อมูลที่นำเข้าเป็นสเกล 10000 และ HP มอนที่เป็นศูนย์คงศูนย์ตามรูปแบบ upstream
- Invasion ใช้สถานะ challenge ที่โหลดจริง `battle_config.enable_invasion_support` เปิดบัฟ support เพิ่มได้ (ค่าเริ่มต้น false)
- เลิกสร้าง Material ID ด้วยสูตร `130000 + AvatarID` ซึ่ง Client หาไม่พบ และไม่ตอบข้อมูลว่างให้โมดูล RogueTourn/ChenLing ที่ยังไม่รองรับ
สถานะรอบนี้: build ผ่าน วาง binary ที่ root แล้ว ผู้ใช้ยืนยันทั้ง Calyx และ Stagnant Shadow เข้า Battle ได้ โดย log ของเส้นทางตีมอนเวลา 11:53:08 มี BattleInfo และเวลา 11:53:16 มี `PVEBattleResult` ผลนี้ยังไม่ใช่การรับรองโหมดต่อสู้ทุกประเภท
แก้โปรไฟล์เพิ่มเติม: field 4 ของ GetPlayerBoardDataScRsp คือการ์ดส่วนตัว, field 8 คือรูปโปรไฟล์ และ field 9 คือตัวละครช่วยเหลือ โค้ดเดิมใส่ ID ผิดประเภทและไม่มี head frame/display data ปรับให้ใช้ `resources/AvatarPlayerIcon.json`, `resources/ProfileConfig.json` และทีมจริง พร้อมเติม ArchiveData ทั้งสอง response ผู้ใช้ยืนยันหน้าตัวละครหายค้างหลังเปิดเกมใหม่
## โครงสร้างซอร์ส
```text
cmd/gameserver/ จุดเริ่ม game server
cmd/sdkserver/ จุดเริ่ม SDK/dispatch server
internal/common/ โมเดลข้อมูล, resource loader และ protobuf converters
internal/gameserver/ Gateway, session, dispatch และ game handlers
internal/sdkserver/ HTTP dispatch, login และ REST API
protocol/proto/ Schema, generated protobuf และตาราง CmdID
pkg/kcp/ KCP transport
resources/ ข้อมูลประกอบ
scripts/ Client Lua
```
## อัปเดต protocol และ handler
ใช้ checkout ของ PearlSR ที่ตรวจ revision แล้วเป็นแหล่งข้อมูล ไม่แก้ generated Go ด้วยมือ:
```powershell
python tools/sync_protocol_commands.py "<path-to-pearl-sr-checkout>"
protoc --go_out=. --go_opt=paths=source_relative protocol/proto/StarRail.proto protocol/proto/current_handlers.proto
python tools/audit_protocol_handlers.py "<path-to-pearl-sr-checkout>"
```
คำสั่ง sync อัปเดตตารางชื่อ/CmdID ส่วนการแก้ field ต้องตรวจจาก schema ต้นฉบับแล้วแก้ `.proto` ก่อน generate ใหม่ ตัว audit ตรวจ CmdID, คู่ request/response และชุดหมายเลข field ของ message ที่มีชื่อร่วมกัน ไม่ตรวจชนิด field, default values, asset หรือผลใน Client
`ClientDownloadDataLuaVersion = 51` เป็นค่า version ของ payload ที่ upstream ปัจจุบันยังใช้ส่ง Lua จึงไม่เปลี่ยนเป็น `53` ตาม `client_version` โดยไม่มีหลักฐานรองรับ ส่วน Tutorial อ่าน ID จาก `resources/TutorialData.json` และ `resources/TutorialGuideGroup.json` หลังเปลี่ยน resource ให้รีสตาร์ต server
## ที่มา
พอร์ตจาก `GaC-hkrpg-ps` ภาษา Rust โดยใช้แนวทางและข้อมูลประกอบจาก [HonkaiSlopRail/pearl-sr](https://git.xeondev.com/HonkaiSlopRail/pearl-sr) ภาษา Zig การแก้ใน Go ต้องตรวจเทียบทั้ง handler, payload และเวอร์ชัน Client ที่ใช้งานจริง