fix: sync current handlers, repair relic data and restore visible launcher consoles
This commit is contained in:
1 parent
163d4433e6
commit
74f3c4411b
46 files changed
+4599
-1402
No files matched your search
@@ -0,0 +1,77 @@
|
||||
# Battle investigation — 2026-10-16
|
||||
|
||||
## หลักฐานที่ใช้อ้างอิง
|
||||
|
||||
- Upstream: [HonkaiSlopRail/pearl-sr](https://git.xeondev.com/HonkaiSlopRail/pearl-sr)
|
||||
- ตรวจ remote ใหม่แล้วที่ commit `005d2c12db4781071f4b5b68e8f364587886a710`
|
||||
- ไฟล์หลัก: `gameserver/src/services/battle.zig`, `gameserver/src/manager/battle_mgr.zig`, `gameserver/src/data/game_config.zig`, `protocol/src/protocol.pb.zig`
|
||||
- Client ล่าสุดยัง NRE ที่ `CreateBattleServerCheckResult` ผ่านตัวแปลง BattleAvatar/รายการ relic และ `NMBMHCNGCFG.BDNFEMGIEIH`
|
||||
- Payload ที่บันทึกเวลา 21:34 มีตัวละคร 4 ตัว แต่ละตัวมี relic 6 ชิ้นและ sub-affix 24 ค่า แม้เลิกส่ง inventory UniqueId ใน BattleRelic แล้ว Client ก็ยังล้ม
|
||||
|
||||
## เทียบทีละส่วน
|
||||
|
||||
| ส่วน | สิ่งที่ตรวจพบ | ข้อสรุปที่ใช้ได้ |
|
||||
| --- | --- | --- |
|
||||
| Quick Calyx response | Field numbers: retcode=1, battle_info=5, wave=8, cocoon_id=11 ตรง upstream | ยังไม่พบ field-number mismatch ใน wrapper |
|
||||
| SceneBattleInfo | ตรวจชุด field numbers ของ 20 fields ตรงกัน | ชื่อ `JAOIOKBBMFC` ของ Go คือ field 7 ซึ่ง upstream เรียก monster_wave_length |
|
||||
| BattleAvatar | ตรวจชุด field numbers ของ 18 fields ตรงกัน | ยังต้องดูค่าที่ parser ของ Client ถอดได้จริง |
|
||||
| Relic/lightcone | BattleRelic, RelicAffix และ BattleEquipment มีชุด field numbers ตรงกัน | จำนวน sub-affix ฝั่ง Go อย่างเดียวไม่ยืนยันว่า Client ถอดได้ครบ |
|
||||
| Monster/wave | SceneMonster, SceneMonsterWave, SceneMonsterWaveParam มีชุด field numbers ตรงกัน | ยังไม่มีหลักฐานให้สลับ WaveParam เป็น nil อีก |
|
||||
| Buff | Go ใช้ชื่อ OwnerId แต่ upstream ใช้ owner_index บน field 3 เหมือนกัน | ชื่อ Go ไม่ใช่หลักฐานว่า field บน wire ผิด |
|
||||
| แหล่งข้อมูล | Go ใช้ freesr-data.json/persistent; PearlSR ใช้ config.json/selected avatars | Payload ทั้งสองยังไม่เท่ากันในระดับค่าข้อมูล |
|
||||
| EX rank | Upstream append รายการ ExRankAvatarID ให้ทุก battle avatar; Go ส่งรายการตามตัวละครที่ปลดล็อก | เป็นข้อแตกต่างที่บันทึกไว้ ยังไม่ชี้ว่าเป็นสาเหตุ NRE |
|
||||
| Global/technique buffs | เจ้าของบัฟ, target list และ dynamic values บางตัวต่างกัน | ต้องตรวจแยกหลังระบุตำแหน่งที่ parser/ตัวตรวจล้ม |
|
||||
|
||||
การตรวจ field numbers ข้างต้นไม่ได้ยืนยัน default values, Client schema ของรุ่นที่รันจริง หรือผลการคำนวณค่าสถานะใน Client
|
||||
|
||||
## ขั้นแรกที่เพิ่มในรอบนี้: เก็บ wire และอ่านกลับบน Client
|
||||
|
||||
บันทึกหลังส่ง response สำเร็จจาก Session.Send แทนการบันทึกระหว่างสร้าง battle:
|
||||
|
||||
- `battle_last_response.bin`: protobuf body ของ response ที่ส่งจริง
|
||||
- `battle_last.bin`: bytes ของ nested battle_info ที่ตัดออกจาก response เดิมโดยตรง ไม่ marshal ใหม่
|
||||
- `battle_last.json`: ข้อมูลสำหรับอ่านด้วยตา
|
||||
- `battle_last_capture.json`: CmdID, ชื่อ response, StageID, เวลา UTC และ SHA-256
|
||||
- `battle_diagnostics/`: snapshot ของแต่ละรอบ เก็บทั้งข้อมูลเดิมและรอบต่อมา
|
||||
|
||||
เปิด read-only Client probe ด้วย `battle_diagnostics.client_battle_type` ใน local config ชื่อ class ต้องเอาจาก stack trace ของ Client รุ่นที่กำลังใช้งาน ไม่ฝังชื่อ class ที่เปลี่ยนตามเวอร์ชันใน Go/Lua
|
||||
|
||||
Probe ถูกส่งครั้งเดียวใน heartbeat หลัง response battle โดยใช้ protobuf parser ของ Client อ่าน bytes เดียวกับ capture จากนั้นเขียน `[GAC_BATTLE_WIRE]` ลง Player.log พร้อม decoded JSON และ descriptor field numbers ไม่แก้ตัวละคร relic บัฟ หรือ callback การต่อสู้
|
||||
|
||||
หาก parser/Reflection ไม่ถูกเปิดให้ Lua ใช้ จะมี `probe_error` ใน Player.log แทน ห้ามตีความว่า capture ฝั่ง Go ผ่านแล้วแปลว่า Client decode ผ่าน
|
||||
|
||||
## ข้อสรุปที่ถอนออก
|
||||
|
||||
Stack trace เดิมเพียงอย่างเดียวไม่ได้พิสูจน์ว่า WaveParam=nil หรือ SceneMonster.ExtraInfo=nil เป็นสาเหตุ การใส่ ExtraInfo หรือการลบ UniqueId ยังไม่ได้ทำให้การเข้า battle สำเร็จ จึงไม่ถือเป็นการแก้ที่ยืนยันผลแล้ว
|
||||
|
||||
## ผลตรวจรอบ 21:47: main affix ที่ไม่มีในตาราง
|
||||
|
||||
Calyx และ overworld ตายที่ stack เดียวกัน ส่วน probe รุ่นแรกทำงานแล้วแต่รายงาน `protobuf parser property not found` จึงไม่มี Client readback และยังใช้ผลของ probe ยืนยันการ decode ไม่ได้
|
||||
|
||||
แก้การอ่านตำแหน่ง exception: `0xc4eb77c` เป็น return address หลังคำสั่ง `call` ที่ `0xc4eb777` เช่นเดียวกับ frame `0x166b23d2` ที่อยู่หลัง `call 0xc4eb0c0` ดังนั้นจุดนี้มาจาก branch หลัง lookup **main affix** ไม่พบ (`0xc4eb2b0`–`0xc4eb2b3`) ไม่ใช่ branch ตรวจ sub-affix array ที่กระโดดไป `0xc4eb77c` แล้วมี return address `0xc4eb781` การตีความ sub-affix array เป็น null ในรอบก่อนจึงถูกถอนออก
|
||||
|
||||
ตรวจ payload จริงและ inventory พบรายการนี้:
|
||||
|
||||
| Inventory UID | Avatar | Relic | main_affix_id เดิม | ผลตรวจ |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 483 | 1213 (Dan Heng IL) | 63095 | 11 | ไม่มีใน main affix group 55 ของลูกแก้ว |
|
||||
|
||||
เทียบกับ [relics.json](https://github.com/Mar-7th/StarRailRes/blob/dbe8cdfcfb0bf657b9fe1cf92d5537f118ccb487/index_new/en/relics.json) และ [relic_main_affixes.json](https://github.com/Mar-7th/StarRailRes/blob/dbe8cdfcfb0bf657b9fe1cf92d5537f118ccb487/index_new/en/relic_main_affixes.json): group 55 มี ID 1–10 โดย ID 10 คือ `ImaginaryAddedRatio` และ `resources/AvatarConfig.json` ระบุ Avatar 1213 เป็น Imaginary
|
||||
|
||||
แก้ **ข้อมูล inventory เท่านั้น** จาก 11 เป็น 10 ใน `freesr-data.json` ไม่มีเงื่อนไขพิเศษสำหรับ Avatar/Relic นี้ใน converter สำรองข้อมูลและ log ก่อนแก้ไว้ใน `battle_diagnostics/main-affix-repair/` แล้ว และปิด probe ใน local config ขณะลองผลการแก้ข้อมูล
|
||||
|
||||
ข้อจำกัดของชุดข้อมูลอ้างอิง: ไม่พบ relic ใหม่ 63295/63296 ของ Avatar 1511 จึงไม่ได้รับรอง inventory ทุกชิ้น แต่ชิ้นที่อยู่ในทีมของ payload รอบนี้มีครบและพบ main affix ผิดหนึ่งชิ้นข้างต้น
|
||||
|
||||
## ขั้นต่อไปหลังแก้ main affix
|
||||
|
||||
1. เปิดเกมใหม่ให้ Client โหลด inventory ที่แก้แล้ว และลอง Calyx/overworld ด้วยทีมเดิม
|
||||
2. หากยังล้ม ให้เก็บ stack ใหม่และเทียบ capture ว่าส่ง main affix 10 แล้ว ก่อนเปลี่ยนส่วนอื่น
|
||||
|
||||
## แนวทางตรวจเพิ่มเติมหากยังล้ม
|
||||
|
||||
1. เทียบ SHA-256 ให้ตรงกับรอบที่ Client ล้ม
|
||||
2. เทียบ schema/ข้อมูล BattleAvatar และ nested relic ที่ Client ถอดได้กับ capture ฝั่ง Go
|
||||
3. หากข้อมูลตรงกัน ให้แยกตัวละครและอุปกรณ์ที่ทำให้ตัวตรวจค่าสถานะล้มโดยมี control payload ก่อนแก้ resource หรือสูตรบัฟ
|
||||
4. เปลี่ยนเฉพาะส่วนที่มีหลักฐาน แล้วตรวจ Calyx และ overworld battle แยกกัน
|
||||
|
||||
สถานะ: ยังไม่มีการยืนยันว่าเข้า fight ได้
|
||||
@@ -0,0 +1,40 @@
|
||||
# Protocol และ handler — 2026-10-16
|
||||
|
||||
เป้าหมาย Client: 4.6.53 OS ตาม config ที่ใช้อยู่
|
||||
|
||||
แหล่งอ้างอิง: [PearlSR commit 005d2c12db4781071f4b5b68e8f364587886a710](https://git.xeondev.com/HonkaiSlopRail/pearl-sr/commit/005d2c12db4781071f4b5b68e8f364587886a710) โดยตรวจ `protocol/src/root.zig`, `protocol/src/protocol.pb.zig` และ `gameserver/src/services/{challenge,misc,avatar}.zig` หลัง fetch remote ใหม่
|
||||
|
||||
## สิ่งที่เปลี่ยน
|
||||
|
||||
| ส่วน | การแก้ |
|
||||
| --- | --- |
|
||||
| ตารางคำสั่ง | Generate ชื่อ/CmdID 2,690 รายการจาก upstream เก็บ revision และตรวจ conflict กับ Go schema เมื่อเริ่มโปรแกรม |
|
||||
| `handle` / raw dispatch | เลิกระบุเวอร์ชันเก่าในข้อความ log และให้ raw handler resolve request ตามชื่อจากตารางปัจจุบัน |
|
||||
| alias เก่า | นำเลข request หลายเวอร์ชันและ fixed-body replies ที่ไม่มีชื่อปัจจุบันรองรับออก บางเลขเคยชี้ไปยัง response/notification เช่น 8909, 8924, 8935 |
|
||||
| Tierce lineup | ใช้ request 8992 → response 8979; challenge_id field 4 และ stage_info_list field 5 ตาม upstream เพิ่ม generated message ที่ Go เดิมขาด |
|
||||
| Tierce data | ตอบ GetChallengeTierceDataScRsp ครั้งเดียว เลิกส่งสำเนาไป cmd 8994 และเลิกรับ response 8979/8981 เป็น request |
|
||||
| Challenge reward | รับ request 1747 → response 1748; อ่าน group_id field 10 และส่ง group_id field 12 / retcode field 9 ด้วย generated type แทน request 1739 → cmd 1704 ที่เป็นคนละระบบ |
|
||||
| Challenge statistics | อ่าน request ด้วย generated type และตอบ group เดิมตาม upstream; ไม่ส่งคะแนนประวัติที่แต่งขึ้น ปรับ statistics สามชนิดเป็น oneof ตาม schema |
|
||||
| ออกจาก Challenge | ส่ง response ตาม mode ที่ร้องขอเพียงชนิดเดียว ล้าง battle แล้วใช้ฉาก overworld ที่เก็บไว้ของผู้เล่น เลิกบังคับไปฉาก/พิกัดคงที่ |
|
||||
| Peak | ลงทะเบียน StartChallengePeak ที่มี implementation อยู่แล้ว และ LeaveChallengePeak ด้วยชื่อปัจจุบัน; GetCurChallengePeak ตอบสถานะว่างแบบ upstream แทน PeakID 1 ที่แต่งขึ้น |
|
||||
| Endgame / SwitchHand | ส่ง generated response โดย resolve CmdID ตามชื่อ แทน raw bytes และเลขที่ฝังใน handler |
|
||||
| Avatar cmd 400 | อ่าน field จาก generated HIGLJHLNODG แทนการสแกนเลขทุก field และเลิกยิง response 5 หมายเลข; ใช้ LPOLGDLAADM ซึ่งอยู่คู่ติดกันใน schema ชื่อและความสัมพันธ์เชิงความหมายยังเป็น obfuscated จึงยังต้องยืนยัน callback ใน Client |
|
||||
| ReplaceLineup | เพิ่ม field 14 `OMDLCGEMBLA` ที่ Go schema ขาดตาม upstream โดยไม่เดาค่าให้ field นี้ |
|
||||
| Tutorial | เลิกใช้รายการ ID จาก Rust 4.6.51; อ่าน TutorialID/GroupID จาก resource JSON ที่ติดตั้งแทน และรายงาน error หากไฟล์หาย/ไม่มี ID |
|
||||
| Activity | นำ generated list เก่าที่ไม่ได้ใช้แล้วออก ไม่เปิด activity panel เพิ่มก่อนมี implementation รองรับข้อมูลของมัน |
|
||||
| Lua heartbeat | คงค่า version ของ ClientDownloadData ไว้ที่ 51 เพราะ `services/misc.zig` ของ upstream revision นี้ยังส่งค่านี้ ไม่อนุมานจากเลข client patch |
|
||||
|
||||
Go message บางชื่อเป็น alias เก่าของชื่อที่ upstream ตั้งใหม่ เช่น StartQuickCocoonStage/QuickStartCocoonStage และ TakeChallengeReward/TakeChallengeCumulativeReward คงชนิด Go เดิมในจุดที่ wire layout ตรงกัน แล้วผูกหมายเลขคำสั่งกับตารางปัจจุบัน
|
||||
|
||||
## ผล source audit
|
||||
|
||||
- CmdID 2,690 รายการตรงกับ upstream
|
||||
- คู่ request/response เดิม 865 คู่ตรงกับ upstream
|
||||
- ชุดหมายเลข field ของ message ที่มีชื่อร่วมกัน 4,435 ชนิดตรงกันหลังนับ oneof ทั้งสองฝั่ง
|
||||
- การตรวจนี้ไม่ครอบคลุมความหมายของชื่อ obfuscated, ชนิด/default ของทุก field, resource รุ่นที่ตรง Client หรือผลการเล่นจริง
|
||||
|
||||
เพิ่ม `tools/sync_protocol_commands.py` สำหรับ generate ตารางคำสั่ง และ `tools/audit_protocol_handlers.py` สำหรับตรวจซอร์สซ้ำ โดยระบุ checkout ของ upstream เป็น argument ไม่ฝัง path เครื่อง
|
||||
|
||||
## ขอบเขตที่ยังเหลือ
|
||||
|
||||
การเปลี่ยนนี้อัปเดต dispatch/schema/handlers ข้างต้น ไม่ได้อ้างว่า implementation ของทุกระบบเสร็จแล้ว ข้อมูลปลดล็อก, สูตร fallback ด่าน, บัฟ และสถิติบางส่วนของโปรเจกต์ยังต้องตรวจแยกตาม resource จริง การ build หรือ source audit ผ่านไม่ยืนยันว่า Calyx, teleport หรือ Endgame ทำงานสำเร็จใน Client
|
||||
Reference in new issue
Block a user