CAtlas0784 5cc172239d feat(activity): real 4.6.51 activity schedule from March7th dump
The synthetic 1000-60000 ranges filled the Travel Log with entries the
client cannot resolve. Replaced with the 147 real (activityId, panelId)
rows dumped from the March7th PS ActivityConfig (matches the 4.6.51
client), keeping the Apocalyptic Shadow panel 21001 block that the AS
tab requires
2026-10-07 02:16:08 +07:00

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 ทำงานเหมือนเดิม)
S
Description
most slop ps ever create
Readme
7.9 MiB
0 Stars 1 Watchers 0 Forks
Languages
Go 94.7%
Lua 3.7%
Python 1.4%
JavaScript 0.1%
PowerShell 0.1%