Files

88 lines
10 KiB
Markdown
Raw Permalink Normal View History

# บันทึกความจำ 2026-10-10: แก้ไข Endgame Modes ทั้ง 7 ข้อ (4.6.51)
## ปัญหาที่พบและวิธีแก้ไขครบทั้ง 7 ข้อ
### ข้อ 1: กด Apocalyptic Shadow ในแท็บ Latest Update แล้วขึ้น Error(100)
- **สาเหตุ:** Client ส่ง cmd `1775` (`GetChallengeGroupStatisticsCsReq`) ซึ่งโค้ดเดิมใช้ byte slicing แบบ 4.5.52 เก่าที่มี tag ผิดเพี้ยน (`group_id=9`, `retcode=15`, `challenge_boss=11`) ทำให้ client 4.6.51 parse ไม่ได้แล้วโยน Error(100)
- **การแก้ไข:** ใน `internal/gameserver/handlers_raw.go` เขียน `challengeGroupStatsReply` ใหม่โดยใช้ `goproto.GetChallengeGroupStatisticsScRsp` ตาม proto 4.6.51 โดยตรง:
- `group_id = 5`
- `retcode = 9` (0 = สำเร็จ)
- AS: `challenge_boss = 1`
- PF: `challenge_story = 3`
- MoC: `challenge_default = 11`
### ข้อ 2: AS Starward (cmd 8986 `StartChallengeTierceCsReq`, challenge 30225) เข้าไม่ได้
- **สาเหตุ:**
1. `mapChallengeStageID` ฝืน map id 30200..30300 ทุกตัวไปเป็น 30204 (ซึ่ง 30204 ไม่มีใน `tierce`)
2. `decodeStartChallengeTierceReq` ตรวจหาเฉพาะ tag 12/14 (4.5.52) แต่ client 4.6.51 ส่ง `LineupTierceList` ใน tag 9
3. `handleStartChallengeTierce` ตรวจสอบ `cd.Tierce` เฉพาะเมื่อ `stageIndex == 2` ทำให้ stageIndex 0 หลุดไปหา 3014101 -> 3000101
4. Response ตอบด้วย cmd 8973 (4.5.52) แทนที่จะเป็น 8998 (4.6.51)
- **การแก้ไข:**
1. `mapChallengeStageID` คืนค่า id ทันทีถ้า id มีอยู่ใน `cd.Challenges` หรือ `cd.Tierce` (30225 คืน 30225)
2. `decodeStartChallengeTierceReq` parse ผ่าน `proto.Unmarshal(&goproto.StartChallengeTierceCsReq)`
3. `handleStartChallengeTierce` ดึงข้อมูลจาก `cd.Tierce[baseID]` ทุก stageIndex ได้ entrance `3012602`, group `7`, monster `2034012`, event `420554`
4. ตอบด้วย `goproto.StartChallengeTierceScRsp` ผ่าน CmdID **8998** (และ legacy 8973)
### ข้อ 3: AS Normal (cmd 1731 `StartChallengeCsReq`, challenge 30224) เข้าไม่ได้
- **สาเหตุ:**
1. `mapChallengeStageID` ฝืน map 30224 -> 30204
2. `decodeStartChallengeReq` มี wire slicing bug (`buf = buf[len(buf)-len(sub):]; buf = buf[len(sub):]`) ทำให้ buf desync และพลาด challenge_id
- **การแก้ไข:**
1. `mapChallengeStageID` เช็ค `cd.Challenges[30224]` แล้วคืน 30224 ตรงๆ
2. `decodeStartChallengeReq` ใช้ `proto.Unmarshal(&goproto.StartChallengeCsReq)` + helper `readLenDelimAndAdvance`
3. `handleStartChallenge` ตอบ `StartChallengeScRsp` (1787) ครบทั้ง 2 Node
### ข้อ 4: ออกจาก Endgame แล้วตัวละครหาย
- **สาเหตุ:**
1. `loadChallengeScene` ไปเขียนทับ `player.Scene.EntryID = entryID` ทำให้ open world กลายเป็นฉาก arena (3000501/3000101) และถูกบันทึก persistent
2. `handleLeaveChallenge` และ `handleLeaveChallengeTierce` ส่งเฉพาะ ScRsp เก่า (1716, 8997) โดยไม่ส่ง `loadScene` เพื่อพาผู้เล่นกลับ open world
- **การแก้ไข:**
1. นำบรรทัดเขียนทับ `player.Scene` ออกจาก `handlers_challenge_scene.go`
2. `handleLeaveChallenge` ตอบ CmdID **1771** (`LeaveChallengeScRsp`, tag 10 retcode 0 `[0x50, 0x00]`) แล้วเรียก `loadScene(s, returnEntry, true, nil, nil)` สั่ง `EnterSceneByServerScNotify` (1427) ดึงตัวละครกลับฉากเดิม
3. `handleLeaveChallengeTierce` ตอบ CmdID **8983** (`LeaveChallengeTierceScRsp`, tag 13 retcode 0 `[0x68, 0x00]`) แล้วเรียก `loadScene` เช่นกัน
### ข้อ 5: PF Starward หมุนค้างตอนจัดทีมตัวละคร
- **สาเหตุ:** Client ส่ง cmd `8978` / `9000` (`SetChallengeTierceLineupCsReq`) ซึ่ง callback ใน GameAssembly.dll (`OMOEFAHFJFL::EMMGHDLIPOH`) รอ CmdID **8985** (`SetChallengeTierceLineupScRsp` / `CmdChallengeTierceType_PMMCIBMKOLD`) แต่เซิร์ฟเวอร์ส่ง 8999 ทำให้ client ไม่เคยได้รับ callback และหมุนค้าง
- **การแก้ไข:** ใน `handleSetChallengeTierceLineup` ส่ง CmdID **8985** ด้วยบอดี้ `[0x08, 0x00]` (tag 1 retcode 0) และแมพทั้ง 8978 และ 9000 ใน `rawHandlers`
### ข้อ 6: PF Normal (challenge 20284) เข้าไม่ได้
- **สาเหตุ:**
1. `mapChallengeStageID` map 20284 -> 20254
2. `handleStartChallenge` ส่ง `stage_info` (tag 13) เป็นก้อนว่างสำหรับโหมด PF ทำให้ client เกิดปัญหา
- **การแก้ไข:**
1. ไม่ map 20284 เพราะมีใน `cd.Challenges[20284]`
2. `stage_info` (tag 13) จะแนบเฉพาะเมื่อ `challengeID >= 30000 && buff != 0` (AS Boss เท่านั้น) ส่วน MoC และ PF จะเป็น nil (ไม่ปล่อย tag 13)
### ข้อ 7: MoC Normal (challenge 5612) ค้างหน้าโหลดเหลือ 1 ขีด
- **สาเหตุ:**
1. ทันทีที่เข้าฉาก arena client ส่ง cmd `8115` (`GetSwitchHandDataCsReq`) แต่เซิร์ฟเวอร์ตอบด้วย cmd `8104` (ซึ่งเป็น CsReq: `SwitchHandStartCsReq`) ทำให้ client สับสนและค้าง loading notch สุดท้าย
2. `mapChallengeStageID` มีการเพี้ยน id 5612
- **การแก้ไข:**
1. แก้ cmd `8115` ให้ตอบ CmdID **8108** (`GetSwitchHandDataScRsp`, body `[0x18, 0x00]`)
2. `mapChallengeStageID` คืน 5612 ตรงๆ จาก `cd.Challenges[5612]` (entrance 3013801)
### ข้อ 8: ค้างหน้าจอโหลด 100% (รูปรถไฟ Astral Express หมุนไม่ไปต่อ)
- **สาเหตุจาก Player.log:**
1. **DrinkMaker NRE:** Client ส่ง cmd `6995` (`GetDrinkMakerDataCsReq`) แต่ `dispatch.go` ตอบกลับด้วย `6988` payload เปล่า (`len: 0`) เพราะไม่อยู่ใน `dangerFamilies` ส่งผลให้ `DrinkMakerBar._UpdateGameplayData()` ใน Unity client เจอก้อน nil แล้ว crash `NullReferenceException`
2. **MapNPC Astral Express NRE:** บันทึก `persistent` ถูกตั้งไว้ที่ `entry_id: 100000104` (Astral Express Parlor Car `P10000_F10000000`) ซึ่งใน client 4.6.51 นี้ ไฟล์ config ของ Chapter00 มีปัญหา (`TerrainStageLodConfig ... 没找到`) และ `MapNPC:227-400001` ไม่มี ConfigEntityPath ทำให้ `AsyncLoad MapObject` โยน `NullReferenceException` ระหว่างขั้นตอน `AdventurePhase._EnterStep2()` ค้างโหลด 100% แล้วแอปเด้งปิด
- **การแก้ไข:**
1. เพิ่ม `"DrinkMaker"` ลงใน `dangerFamilies` และเพิ่ม CmdID `6995, 6988` ใน `isDangerCmd` (`dispatch.go`) ให้ drop เงียบๆ ป้องกัน empty ScRsp
2. เปลี่ยน fallback ของ `GetCurSceneInfo` ใน `handlers_scene.go` และ `handleLeaveChallenge` / `handleLeaveChallengeTierce` ใน `handlers_challenge_flow.go` จาก `100000104` เป็น `102020107` (Belobog Administrative District `P10202_F10202001`) ซึ่งเป็นแมพสมบูรณ์ 100%
3. รีเซ็ตไฟล์ `persistent` กลับเป็นแมพ `102020107` พิกัด `x: -92, y: 4278, z: 68083, rot_y: 155566`
### ข้อ 9: Run.bat เปิดไม่ติด (หน้าต่างกระพริบปิดทันที)
- **สาเหตุ:**
1. ในคำสั่ง `if (...)` ของไฟล์ batch มีข้อความ `echo ... (Option 4).` ซึ่งตัวอักษร `)` ไปปิดบล็อก `if` ก่อนกำหนด ทำให้เครื่องหมายจุด `.` กลายเป็นคำสั่งที่ผิดไวยากรณ์ DOS/Windows (`. was unexpected at this time.`) ส่งผลให้ cmd แครชปิดหน้าต่างทันทีตั้งแต่บรรทัดแรกๆ
2. การใช้ข้อความภาษาไทยในไฟล์ .bat ที่บันทึกแบบ UTF-8 ทำให้ cmd.exe ใน codepage เริ่มต้นของ Windows ตีความไบต์ผิดพลาด
- **การแก้ไข:**
1. แก้ไข `run.bat` และ `run_go.bat` ให้เป็น ASCII ที่สะอาด ไม่มีวงเล็บซ้อนในบล็อก `if`
2. เพิ่มตัวเลือกแบบยืดหยุ่น:
- [1] เปิด Server + ตัวเกม / Proxy (Default)
- [2] เปิด Server ทั้งสองตัว (SDK + Game Server)
- [3] เปิดเฉพาะ **SDK Server ONLY** (HTTP 21000)
- [4] เปิดเฉพาะ **Game Server ONLY** (UDP 23301)
- [5] เปิด Server + Gay Proxy
- [6] Build / Rebuild binaries (Go)
- [7] ออก
3. ถ้าเปิดสำเร็จโดยไม่มี error จะนับถอยหลัง 5 วินาทีแล้วปิดหน้าต่าง Launcher ไปเองตามที่ผู้ใช้ต้องการ (และหากมี error จะ pause ค้างไว้ให้อ่าน)