# GaC hkrpg GO — StarRail 4.6.51 Private Server (ภาษา Go) โอนย้าย (port) จากโปรเจกต์ Rust `GaC-hkrpg-ps` มาเป็นภาษา Go ทั้งหมด พร้อม **แก้บัคกล้องหลุดจากตัวละครตอนกดตี (SceneCastSkill)** ตั้งแต่ต้นทาง --- ## บัคกล้องหลุด (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 ทำงานเหมือนเดิม)