2026-10-07 00:31:53 +07:00
|
|
|
# 2026-10-07 — พอร์ตเซิร์ฟเวอร์เป็นภาษา Go + แก้บัคกล้องหลุด (SceneCastSkill)
|
|
|
|
|
|
|
|
|
|
## สรุปงานวันนี้
|
|
|
|
|
|
|
|
|
|
### 1. พบต้นเหตุจริงของบัค "กดตีแล้วกล้องหลุดจากตัวละคร"
|
|
|
|
|
- `SceneCastSkillCsReq` handler เดิม (Rust battle.rs) ตอบ `battle_info` + `monster_battle_info`
|
|
|
|
|
ให้ client เข้า battle กับ target ที่ผ่าน filter หลวม `id > 30000 || id < 1000`
|
|
|
|
|
- filter นี้รวม **avatar entity ของผู้เล่นเอง** (1-4) เข้าไปด้วย → client เริ่ม battle transition
|
|
|
|
|
กับ "monster" ที่ไม่มีอยู่จริง → กล้อง battle ไม่มี target → หลุดจากตัวละคร
|
|
|
|
|
- กรณี arena (entry >= 3000000) โค้ดเดิมยังหลอก target เป็น 30001 เสมออีกชั้น
|
|
|
|
|
|
|
|
|
|
### 2. พอร์ตทั้งเซิร์ฟเวอร์เป็นภาษา Go → `C:\Users\Phitchayut\Desktop\GaC-hkrpg-go` (commit 59ea97b)
|
|
|
|
|
- สาเหตุที่เปลี่ยนภาษา: (1) คำแนะนำจากเพื่อนให้ใช้ GO แทน (Firefly Shelter ที่เวิร์กเป็น Go
|
|
|
|
|
แต่ปิด source) (2) พบว่าโค้ด Rust commit สุดท้าย **แตกตัวกับ proto ใน repo ตัวเอง** —
|
|
|
|
|
ใช้ชื่อ message เก่า (`PveBattleResultCsReq`, `QuickStartCocoonStageCsReq`, `GateServer`,
|
|
|
|
|
`GetGachaInfoCsReq`, `GroupRefreshInfo`, `LineupSlot`) ที่ไม่มีใน proto 4.6.51 แล้ว
|
|
|
|
|
- ตัว Go ผูกทุก handler กับชื่อจริงใน proto (handler ที่ proto ไม่มี → log+skip ไม่ panic)
|
|
|
|
|
|
|
|
|
|
### 3. สิ่งที่สร้าง/พอร์ต
|
|
|
|
|
- `pkg/kcp` — mihoyo KCP (header 28 ไบต์ conv+token) port จาก kcp.rs 1:1 + ใช้นาฬิกา ms
|
|
|
|
|
(Rust ใช้วินาที ทำ RTT/resend เพี้ยน) + UDP loopback test ผ่าน
|
|
|
|
|
- `protocol/proto` — generate Go protobuf จาก proto 4.6.51 (4,932 messages) +
|
|
|
|
|
cmdid map 2,114 ids generate จาก `// CmdID:` comments
|
|
|
|
|
- gameserver ครบ: handshake 0xFF/0x145/0x194, packet framing 0x9D74C714/0xD7A152C8,
|
|
|
|
|
login flow, scene load (props/NPCs/monsters + MonsterEntities tracking), lineup,
|
|
|
|
|
avatar/skin, missions, tutorials (1249+855), bag/equip, challenge ครบ
|
|
|
|
|
(StartChallenge 1787 / Tierce 8973 / Peak 8948 / raw replies ทุกตัว)
|
|
|
|
|
- sdkserver: query_dispatch/query_gateway (Gateserver pb + base64), hotfix fetch,
|
|
|
|
|
auth endpoints, SRTools upload
|
|
|
|
|
- **FIX SceneCastSkill**: เก็บ monster entity จริงต่อ session (`Session.MonsterEntities`)
|
|
|
|
|
ตีไม่โดน monster จริง = ตอบ retcode 0 ไม่เข้า battle → กล้องไม่หลุด
|
|
|
|
|
- smoke test จำลอง client เต็มรูปแบบผ่าน UDP จริง: handshake → PlayerGetToken →
|
|
|
|
|
SceneCastSkill ทั้งสองกรณี — **PASS ทั้งหมด**
|
|
|
|
|
- ใช้ data files เดิมทุกไฟล์ (save ไม่พัง) — เปิดด้วย `run_go.bat`
|
|
|
|
|
|
|
|
|
|
### 4. เครื่องมือที่ช่วย
|
|
|
|
|
- `tools/firefly_dump` (ที่ user เตรียมไว้) — symbol dump ของ Firefly binary ใช้ยืนยัน
|
|
|
|
|
สถาปัตยกรรม + ยืนยันว่า Firefly ปิด source ไม่มี code ให้ก็อป
|
|
|
|
|
- ติดตั้ง Go 1.27.0 (winget) + protoc-gen-go ใหม่ใน session นี้
|
|
|
|
|
|
|
|
|
|
### 5. การจัดการเอกสาร
|
|
|
|
|
- ลบ `GLM_FIX_PROMPT.md`, `PROMPT.md`, `HANDOFF.md` (หมดอายุ — เนื้อหาจำเป็นย้ายเข้า SKILL.md)
|
|
|
|
|
- อัพเดต `SKILL.md` (เพิ่มหัวข้อ 10-12: proto desync, บัคกล้อง, สถาปัตยกรรม Go)
|
|
|
|
|
- ก็อป SKILL.md → `tools/AI TOOLBOX/skills/hkrpg-ps-version-update/SKILL.md` ทั้งสองโปรเจกต์
|
|
|
|
|
|
|
|
|
|
## สิ่งที่ต้องทำต่อ
|
|
|
|
|
1. **ทดสอบกับ client จริง** — เปิด `run_go.bat` (GaC-hkrpg-go) แล้ว login ด้วย hosts/proxy เดิม
|
|
|
|
|
2. Gacha handlers ถูก skip (proto 4.6.51 เปลี่ยนชื่อ GetGachaInfoCsReq/DoGachaCsReq) — หาชื่อใหม่จาก dump
|
|
|
|
|
3. ถ้า client ฟ้อง cmd ไหน "Unknown" ให้เช็ค `gameserver.log` แล้วเติม handler ในตัว Go
|
2026-10-07 01:45:10 +07:00
|
|
|
|
|
|
|
|
## เพิ่มเติม (รอบแก้เสาวาป — 01:3x)
|
|
|
|
|
|
|
|
|
|
**อาการ:** เสาวาปในแมพใหม่ๆ มองเห็นในแมพแต่ไม่เปิด + กดวาปไม่ไป (client ไม่ส่ง EnterScene เลย)
|
|
|
|
|
|
|
|
|
|
**ต้นเหตุ:** `mapDefaultEntranceMap` ใน res.json ครอบคลุมแค่ 115/371 ฟลอร์ — โค้ด GetSceneMapInfo
|
|
|
|
|
และ EnterScene resolution พึ่งมันทั้งคู่ ฟลอร์ที่ไม่อยู่ในนี้ = ไม่มีรายชื่อเสาปลดล็อคส่งกลับ
|
|
|
|
|
→ client ล็อคเสา และไม่เริ่มวาป
|
|
|
|
|
|
|
|
|
|
**แก้ (commit 0fdadd0):**
|
|
|
|
|
- `findEntryForFloor` — หา entry จากชื่อ config `P*_F<floor>` โดยตรง (mapDefaultEntranceMap เป็น first chance)
|
|
|
|
|
- GetSceneMapInfo รวมรายชื่อเสาจาก teleports.json ทุกฟลอร์
|
|
|
|
|
- EnterScene: teleport id ผ่าน scene_identifier (MDAIDPPKOPO.PLIDNBMCIJH) resolve ปลายทางได้
|
|
|
|
|
- loadScene: ใช้ตำแหน่ง teleport จาก teleports.json ตรงๆ ถ้า res ไม่มี id นั้น
|
|
|
|
|
|
|
|
|
|
**บทเรียน:** data index บางตัวใน res.json ไม่ครอบคลุมทุกแมพ — ต้องมี fallback ค้นจากชื่อ config / teleports.json เสมอ
|
2026-10-07 02:22:52 +07:00
|
|
|
|
|
|
|
|
## รอบ 3 (จากการทดสอบ 10 ข้อของ user — commits 876f20d, 5cc1722)
|
|
|
|
|
|
|
|
|
|
1. **StartChallengeCsReq (1731) decode ได้ challenge_id=0** (MoC/PF/AS โหมดธรรมดากดไม่เจออะไร)
|
|
|
|
|
→ เพิ่ม `detectChallengeID` (สแกน varint ทุก field หา id ที่เข้า range/มีใน challenge_data)
|
|
|
|
|
+ 1787 เพิ่ม `stage_info` (tag 13, boss node buff echo) ตาม proto 4.6.51
|
|
|
|
|
2. **GetSwitchHandDataScRsp = 8108** — บันทึกของ Rust บอก 8104 ผิด! (8104 = SwitchHandStartCsReq)
|
|
|
|
|
3. **GetSceneMapInfo (1461) decode FAIL บาง payload** (layout drift) → ย้ายเป็น raw handler + lenient
|
|
|
|
|
wire-walk fallback (map UI ค้าง "Navigation กำลังโหลด" / ไม่เห็นเสา อาจมาจากจุดนี้)
|
|
|
|
|
4. **บัควาปผิดจังหวัด (AA→AP)**: teleport id (1001, 1002...) ซ้ำกันทุกแมพ และโค้ดค้น teleports.json
|
|
|
|
|
ทั่วโลกแบบสุ่มลำดับ → แก้เป็น resolve จาก floor ใน scene_identifier ก่อนเสมอ ห้าม scan ทั่วโลก
|
|
|
|
|
5. **Tierce arena 3014101 → 3000101** (client 4.6.51 ไม่มี MapEntrance 3014101 ตามบทเรียน Rust)
|
|
|
|
|
6. **Event/Travel Log**: เจอ `tools/march7_dump/Config/Custom/ActivityConfig.json` — activity จริง
|
|
|
|
|
147 รายการจาก client 4.6.51 → แทน synthetic ranges เดิม (content packages ตรงกัน 51=51)
|
|
|
|
|
7. ค้างอี้อื่น (Herta ตัวลอย, ห้อง Trailblazer ค้าง, MapRotation) — รอ log หลัง retest (hexdump +
|
|
|
|
|
decode-error log ครบแล้ว)
|
2026-10-07 02:29:11 +07:00
|
|
|
|
|
|
|
|
## รอบ 4 (02:20 session — "เข้าเกมแล้วไม่โหลดต่อ")
|
|
|
|
|
|
|
|
|
|
**Player.log:** `AdventurePhase._EnterStep1_InitializeMapInfo` → "[InitializeMapInfo]
|
|
|
|
|
AdventureModule should not be null." → `RuntimeGroupManager._InitMissionToLegacyGroupRelation` NRE
|
|
|
|
|
→ client ค้างหน้าโหลด ไม่ส่ง SceneEntityMove เลย
|
|
|
|
|
|
|
|
|
|
**ต้นเหตุ:** รอบก่อนเพิ่มการตอบ `GetMapRotationData (6827)` แบบ ScRsp ว่าง → client เข้าสู่
|
|
|
|
|
map-rotation mode ด้วย state ว่าง → พังตอน init แผนที่ (session 01:00 ที่ตอบ=drop กลับเข้าฉากได้ปกติ)
|
|
|
|
|
|
|
|
|
|
**แก้:** กลับไป drop 6827 (เพิ่มใน never-auto-answer) — จนกว่าจะ implement RotaterData จริง
|
|
|
|
|
แบบ Firefly (scene.OnGetMapRotationDataCsReq)
|
|
|
|
|
|
|
|
|
|
**Repo:** push ไปที่ https://github.com/CAtlas0784/GaC-hkrpg-GO.git แล้ว (main @ 29b16b5)
|
|
|
|
|
+ สร้าง branch `Test` และใช้ branch นี้ต่อ (ตามคำสั่ง user)
|
2026-10-07 02:39:41 +07:00
|
|
|
|
|
|
|
|
## รอบ 5 (02:32 session — ค้างหน้าโหลดหมุนๆ + รูปหน้าจอ train window)
|
|
|
|
|
|
|
|
|
|
**ประเด็นสำคัญที่เกือบหลอก:** ตารางเทียบ 4 session พบว่า 01:38 (exe 01:19) เดินได้ 466 moves
|
|
|
|
|
ทั้งที่ตอบ 4190/6827 ครบ — แสดงว่า MapRotation ไม่ใช่ตัวการหลัก
|
|
|
|
|
|
|
|
|
|
**ต้นเหตุจริง:** user วาปไป entry **100000304** ตอน 01:59 (client เสนอเองในแมพ แต่โหลดไม่ได้
|
|
|
|
|
จริง → NRE ที่ AdventurePhase.InitializeMapInfo) และ server **save ฉากพังนั้นทันที**
|
|
|
|
|
→ ทุก login หลังจากนั้นโหลดแมพพังซ้ำ (1418 หด 1998→1671 = คนละฉาก)
|
|
|
|
|
|
|
|
|
|
**แก้ 2 ชั้น:**
|
|
|
|
|
1. รีเซ็ต persistent กลับ entry 102020107 (แมพที่พิสูจน์แล้วว่าเดินได้ใน session 01:00/01:38)
|
|
|
|
|
2. **save-on-move**: loadScene(isEnterScene) แก้แค่ in-memory — persistent จะถูกเซฟโดย
|
|
|
|
|
SceneEntityMove (ทุก 5 วิ) เมื่อ client เดินได้จริงเท่านั้น → แมพพังไม่มีวัน brick save
|
|
|
|
|
(บังเอิญ arena-guard เดิมช่วยด้วย: ฉาก arena ไม่ถูกเซฟอยู่แล้ว)
|
|
|
|
|
|
|
|
|
|
**บทเรียน:** เทียบ log ต้องดู "ฉากที่โหลด" ด้วย — 1418 ต่างกัน = คนละ entry ไม่ใช่โค้ดพัง
|
2026-10-07 02:54:42 +07:00
|
|
|
|
|
|
|
|
## รอบ 6 (หน้ากิจกรรมจอดำ)
|
|
|
|
|
|
|
|
|
|
**อาการ:** เปิดหน้า Events/กิจกรรม → จอดำ
|
|
|
|
|
**ต้นเหตุ:** schedule จริง 147 activities (March7th) ทำให้ client render panel event จริง
|
|
|
|
|
→ ขอข้อมูลราย activity (GetActivityHotData 9113 / GetActiveActivityData 9565 / ฯลฯ)
|
|
|
|
|
→ ได้ค่าว่าง → NRE → ดำ (รูปแบบเดียวกับ danger families)
|
|
|
|
|
**แก้:** revert เป็น synthetic schedule (หน้าเปิดได้ ว่างแต่ไม่ดำ) — เก็บ realActivitySchedule
|
|
|
|
|
ไว้ใน handlers_activity_data.go รอ implement ข้อมูล event รายประเภทก่อน
|
|
|
|
|
**บทเรียน:** schedule row = สัญญาว่าจะมีข้อมูล event ให้ — อย่าส่ง row ที่เราเติมข้อมูลไม่ได้
|