# 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 "" protoc --go_out=. --go_opt=paths=source_relative protocol/proto/StarRail.proto protocol/proto/current_handlers.proto python tools/audit_protocol_handlers.py "" ``` คำสั่ง 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 ที่ใช้งานจริง