Files
GaCy-GO/README.md
T
CAtlas0784 59ea97b1a6 feat: port GaC-hkrpg-ps to Go with SceneCastSkill camera-detach fix
- mihoyo-variant KCP in pure Go (28-byte conv+token header), UDP gateway
  with 0xFF/0x145/0x194 handshake, ms-precision KCP clock + retransmit ticker
- protobuf for 4.6.51 generated from the AstralOS StarRail.proto (4932
  messages) plus CmdID map from // CmdID: comments (2114 ids)
- sdkserver port: query_dispatch/query_gateway (Gateserver pb + base64),
  hotfix fetch, auth endpoints, SRTools freesr-data.json upload
- gameserver handlers: login flow, scene load/spawn with real monster
  entity tracking, lineup, avatar/skin, missions, tutorials (1249+855),
  bag/equip, challenge incl. StartChallenge 1787 layout + Tierce 8973 +
  peak 8948, all raw tierce replies
- SceneCastSkill camera bug fix: only real scene monsters (tracked per
  session) trigger battle; attacking props/NPCs/air replies retcode 0
  without battle_info so the camera stays locked on the character
- end-to-end smoke test simulating a client over real UDP: handshake,
  PlayerGetToken, and both SceneCastSkill paths
- reuses the Rust PS data files unchanged (freesr-data.json, persistent,
  res.json, teleports.json, challenge_data.json, mission_unlocks.json)
2026-10-07 00:22:23 +07:00

111 lines
7.8 KiB
Markdown

# GaC hkrpg GO — StarRail 4.6.51 Private Server (ภาษา Go)
โอนย้าย (port) จากโปรเจกต์ Rust `GaC-hkrpg-ps` มาเป็นภาษา Go ทั้งหมด
พร้อม **แก้บัคกล้องหลุดจากตัวละครตอนกดตี (SceneCastSkill)** ตั้งแต่ต้นทาง
---
## ทำไมต้อง Go (ที่มาของการแปลง)
- Firefly Shelter (`firefly-go`) ซึ่งพิสูจน์แล้วว่าเข้าเกมได้กับ client 4.6.51 เป็น server ภาษา Go
(ไม่มี public source — สำรวจจาก binary จริงด้วย `tools/firefly_dump` ใน repo เดิม)
- โค้ด Rust ล่าสุดใน commit `ebc27a1` แตกตัวกับ proto ใน repo (ใช้ชื่อ message เก่าอย่าง
`PveBattleResultCsReq` / `QuickStartCocoonStageCsReq` ที่ไม่มีใน proto 4.6.51 อีกต่อไป)
การพอร์ตใหม่จึงผูกกับ **proto 4.6.51 จริง** ตั้งแต่ต้น
## บัคกล้องหลุด (SceneCastSkill) — สาเหตุและวิธีแก้
อาการ: กดตีใน overworld แล้วกล้องหลุดออกจากตัวละคร
สาเหตุ (จาก `gameserver/src/net/handlers/battle.rs` เดิม):
handler ของ `SceneCastSkillCsReq` ตอบ `battle_info` + `monster_battle_info` ให้ client
เข้าสู่การต่อสู้กับ target ที่ผ่าน filter แบบหลวม:
```
filter เดิม: id > 30_000 (monster) || id < 1_000 (avatar entity ของผู้เล่นเอง!)
```
เมื่อ client ส่ง hit target เป็น prop / NPC / ตัวผู้เล่นเอง server จะสั่งเข้า battle
กับ "monster" ที่ไม่มีอยู่จริง → battle transition โหลดไม่สำเร็จ → กล้อง battle
ไม่มี target ให้ตาม → กล้องหลุดจากตัวละคร นอกจากนี้ถ้าอยู่ใน arena
(entry >= 3000000) โค้ดเดิมยัง "หลอก" target เป็น 30001 เสมอ
วิธีแก้ (ใน `internal/gameserver/handlers_battle.go`):
1. ตอนโหลดฉาก server เก็บรายการ **monster entity จริง** ไว้ใน `Session.MonsterEntities`
(entity_id → event_id)
2. `SceneCastSkill` ยอมรับเฉพาะ hit target ที่เป็น monster จริงเท่านั้น
3. ถ้าไม่มี monster จริงถูกตี → ตอบ `retcode 0 + cast_entity_id` เฉยๆ **ไม่เข้า battle**
client เล่นแอนิเมชันตีปกติ กล้องค้างกับตัวละคร
4. ตีโดน monster จริง (รวมบอสใน arena 30001) → เข้า battle ตามปกติ
ยืนยันด้วย test อัตโนมัติ: `internal/gameserver/smoke_test.go`
(จำลอง client เต็มรูปแบบ: handshake → login → กดตี ทั้งกรณี ผ่าน UDP จริง)
## สถาปัตยกรรม
```
cmd/gameserver เกมเซิร์ฟเวอร์ (UDP :23301, KCP)
cmd/sdkserver dispatch + login + SRTools (HTTP :21000)
protocol/proto StarRail.pb.go — generate จาก proto 4.6.51 (4,932 messages)
protocol/proto/cmdid.go — ตาราง CmdID (2,114 ids) generate จาก "// CmdID:" comments
pkg/kcp KCP สาย mihoyo (header 28 ไบต์: conv+token) — port จาก kcp.rs 1:1
internal/common FreesrData / persistent / res.json / teleports.json + proto converters
internal/gameserver gateway, packet framing, session, dispatch, handlers ทั้งหมด
internal/sdkserver query_dispatch / query_gateway / auth / srtools / versions.json
```
ไฟล์ข้อมูลใช้ชุดเดิมกับ Rust PS ทุกไฟล์ (freesr-data.json, persistent, res.json,
teleports.json, challenge_data.json, mission_unlocks.json, versions.json) — save เดิมใช้ได้ทันที
## การใช้งาน
```
run_go.bat เมนู 1/2/3/4 เหมือนเดิม
gameserver-go.exe เกมเซิร์ฟเวอร์
sdkserver-go.exe SDK/dispatch
```
ต้องแก้ hosts ของเครื่อง client แบบเดียวกับ Rust PS (หรือใช้ Fiddler/proxy เดิม)
## Build จากซอร์ส
ต้องมี Go 1.27+ และ protoc + protoc-gen-go (เฉพาะตอนแก้ proto):
```
go build -o gameserver-go.exe ./cmd/gameserver
go build -o sdkserver-go.exe ./cmd/sdkserver
go test ./... # รวม smoke test จำลอง client จริง
```
## สิ่งที่พอร์ตครบแล้ว
- Network: mihoyo KCP (conv+token), NetOperation handshake (0xFF/0x145/0x194),
packet framing (0x9D74C714/0xD7A152C8), freesr-data.json hot-reload watcher
- Login flow ครบ (GetToken/PlayerLogin/GetBasicInfo/PlayerLoginFinish + ContentPackage)
- ฉาก: GetCurSceneInfo/EnterScene (โหลด props/NPCs/monsters จาก res.json, teleport
resolution, fallback จุดเกิด), SceneEntityMove (บันทึกตำแหน่ง), InteractProp,
GetNpcTakenReward, GetSceneMapInfo, GetEnteredScene, GetUnlockTeleport
- ทีม: GetAllLineupData/GetCurLineupData/JoinLineup/ReplaceLineup/SwapLineup/
SwitchLineupIndex/ChangeLineupLeader + SceneGroupRefresh/SyncLineup notify
- ตัวละคร/ไอเทม: GetAvatarData (+skin), สวม/ถอด lightcone/relic, RankUpAvatar, GetBag
- ภารกิจ: GetMissionStatus (curversion finished), GetMissionData, GetQuestData,
GetMainMissionCustomValue, UpdateTrackMainMission (จาก mission_unlocks.json)
- บทเรียน: ปดล็อคครบ 1249 tutorials + 855 guides (กันกล้อง/อินพุตค้าง)
- ต่อสู้: SceneCastSkill (**แก้บัคกล้องหลุดแล้ว**), StartCocoonStage,
StartQuickCocoonStage, SceneEnterStage, PVEBattleResult, GetCurBattleInfo,
SceneCastSkillCostMp, บัฟ global (Castorice/SW/Aha 151104)
- Challenge: GetChallenge, GetCurChallenge, GetChallengePeakData, GetCurChallengePeak,
GetActivityScheduleConfig, StartChallengePeak (cmd 8948 → arena 3000101),
StartChallenge → 1787 layout 4.6.51, Tierce (8973) + ทุก raw reply ที่ตอบค้าง
(1708/1716/1781/1704/8997/8999/8923/8920/... ครบตาม packet.rs เดิม)
- Dummy ปลอดภัย: ตอบว่างเฉพาะรายการที่ปลอดภัย ที่เหลือ drop เงียบ
(บทเรียนจาก Rust: ตอบว่างมั่วทำให้ client NRE จอดำ)
## ต่างจาก Rust ที่ควรรู้
- นาฬิกา KCP เป็นมิลลิวินาที (Rust ใช้วินาที — ทำให้ RTT/เวลา retransmit เพี้ยน)
- มี ticker ขับ KCP ทุก 50ms ต่อ session (retransmission ทำงานจริง)
- ชื่อ message ใช้ตาม proto 4.6.51 จริง (แก้ปัญหาชื่อเก่าที่หายไป)
- StartChallenge ยังไม่รองรับ challenge_id ที่อยู่นอก challenge_data.json
(fallback arena 3014101 ทำงานเหมือนเดิม)