# บันทึกความจำ 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 ค้างไว้ให้อ่าน)