Files
GaCy-GO/docs/GLM-BETA-EVENTS.md
T

225 lines
20 KiB
Markdown
Raw Normal View History

2026-10-28 18:54:43 +07:00
# ข้อมูลกิจกรรม Client Beta สำหรับ GLM
อัปเดต 24 ตุลาคม 2026 (Asia/Bangkok) — ตรวจจาก resource/capture ที่มีอยู่เท่านั้น ไม่ได้แก้ production code ไม่ส่ง probe ไม่รัน tests และไม่รีสตาร์ตเกมหรือเซิร์ฟเวอร์ในงานจัดทำเอกสารนี้
ตำแหน่งชุดข้อมูลรวมและ manifest ของไฟล์ให้ดู [GLM-BETA-DATA.md](GLM-BETA-DATA.md) ภายใน package มี:
- `derived/event-index.json` — join panel/activity/modules พร้อมเงื่อนไขและสถานะ asset/policy
- `derived/event-index.csv` — รายการสำหรับค้น/กรองได้สะดวก
- `derived/preview-schedules.json` — schedules ที่ source/policy ปัจจุบันเลือกได้
- raw `PreviewGameplayCatalog.json`, `PreviewAssetAvailability.json` และ policy ที่ใช้ทำ index
## 1. สรุปสิ่งที่พบ
**ข้อมูลกิจกรรมมีอยู่ใน Beta นี้แล้ว** การหา type ชื่อหนึ่งไม่พบ หรือหน้ากิจกรรมยังไม่แสดง ไม่ได้แปลว่าไม่มีตารางกิจกรรมใน Client
ไฟล์หลักคือ `resources/PreviewGameplayCatalog.json`:
- Client assembly SHA-256: `4aa08a0706f27d2cf9951b61920c179140ece9ea94f7e34422c18e46922939b6`
- Evidence: `ev_9ea0f171c212f18ef6442f116c0bd14dd3ba08a3c583141c9bad58a5d2c7bd27`
- `panels`: **181 แถว** ของ `RPG.GameCore.ActivityPanelRow`
- `activities`: **361 แถว** ของ `RPG.GameCore.ActivityConfigRow`
- ในไฟล์เดียวกันมี Gacha 6 แถว และ Parkour 13 แถว ซึ่งเป็นคนละระบบ
นี่เป็นข้อมูลทั้งหมดของ **สี่ตารางที่ capture ชุดนั้นอ่านได้** ไม่ใช่การ extract ทุกตาราง/ทุก asset/ทุก script ของเกมทั้งชุด และไม่ใช่รายการ event ที่เปิดจริงในวันหนึ่งโดยอัตโนมัติ Client เก็บ historical/future rows ร่วมกันได้
ตารางที่ยืนยันว่ามีชื่อดังนี้:
```text
RPG.GameCore.ActivityPanelRow
RPG.GameCore.ActivityConfigRow
RPG.Client.ActivityModule
```
การ probe `RPG.GameCore.ActivityModuleRow` เคยได้ nil เพราะเป็นชื่อที่ลองหา ข้อนี้ไม่ใช่หลักฐานว่า ActivityModuleIDList หรือระบบกิจกรรมหายไป
## 2. เหตุที่กิจกรรมยังไม่แสดง
`internal/common/activity_preview.go` ปัจจุบันกรองตาม `ActivityPreviewPolicy.json` ไม่ได้ส่งทุกแถวใน Client กลับไปเสมอ
เงื่อนไขก่อนประกาศ preview คือ:
1. UIPrefab ต้องอยู่ใน policy-listed family และมี handler ที่รองรับ
2. `PreviewAssetAvailability.json` ต้องระบุว่า UIPrefab และ TabIcon มีจริงทั้งคู่
3. `DisplayItemList` ต้องว่าง เพื่อไม่กลับไป trigger missing-item/invalid-item errors ที่เคยพบ
4. module ที่ถูกอ้างโดยหลายกิจกรรมต้อง resolve เป็น prefab/handler ที่ตรงกัน ไม่มี first-match เงียบ ๆ
ผลนับจาก resource และ source ปัจจุบัน:
| รายการ | จำนวน |
| --- | ---: |
| Panel rows ทั้งหมด | 181 |
| Activity rows ทั้งหมด | 361 |
| Unique prefab/icon paths ที่เคยตรวจ | 290 |
| Panels ที่ prefab และ icon มีทั้งคู่ | 146 |
| Panels ที่ไม่มี prefab | 27 |
| Panels ที่ไม่มี icon | 30 |
| Prefab families ที่ policy อนุญาต | 19 |
| Panels ที่ผ่าน policy + assets + no display items | 56 |
| Unique preview module schedules | 121 |
| QuestState schedules | 111 |
| GetMultipleDropInfo schedules | 10 |
| Conflicting module-to-panel mappings ใน selected set | 0 |
| Activity rows ที่ไม่พบ effective panel row ใน capture นี้ | 99 |
จำนวนไม่มี prefab/ไม่มี icon มีบางแถวซ้ำกัน จึงห้ามนำ 27 กับ 30 มาบวกแล้วลบจาก 181 ตรง ๆ
146 panels ที่มี asset ครบ **ไม่ได้แปลว่าเปิดเล่นได้ 146 กิจกรรม** ยังมี reward dependencies, data proxies, entry handlers, unlock/finish checks และ state machine ของแต่ละระบบที่ต้องต่อ
## 3. รายการที่หาเจอและควรใช้เริ่มไล่ Beta features
ชื่อด้านล่างเป็น **ชื่อเทคนิคจาก UIPrefab** ไม่ใช่ชื่อภาษาอังกฤษ/ไทยที่ยืนยันแล้วจาก TextMap และเลข ID สูงไม่ได้พิสูจน์เองว่า event นั้นเปิดจริงใน Beta รอบปัจจุบัน
ทุกแถวในตารางยกเว้น BlindBox ตรวจพบทั้ง prefab และ icon ใน installed asset index แล้ว:
| Activity / Panel ID | Technical panel | ActivityModuleIDList | ResidentModuleList | EarlyAccessContentID | Asset |
| --- | --- | --- | --- | ---: | --- |
| 50132 | QuestMechCraftPanel | 5013201 | 5013202 | 150132 | prefab + icon มี |
| 50142 | QuestComicDessertPanel | 5014201 | 5014202 | 150135 | prefab + icon มี |
| 50143 | QuestRealityShowPanel | 5014301–5014305 | 5014311–5014315 | 0 | prefab + icon มี |
| 50125 | QuestFinalityBattlePanel | 5012501–5012505 | ว่าง | 0 | prefab + icon มี |
| 50114 | QuestTeamTowerPanel | 5011401 | 5011402 | 150078 | prefab + icon มี |
| 50112 | QuestPixAirPanel | 5011201 | 5011202 | 150076 | prefab + icon มี |
| 50111 | QuestB51RacingPanel | 5011101 | 5011102 | 150079 | prefab + icon มี |
| 50107 | QuestChenLingFesPanel | 5010701 | ว่าง | 150077 | prefab + icon มี |
| 50092 | QuestChenLingBattlePanel | 5009201 | 5009202 | 150074 | prefab + icon มี |
| 50134 | QuestBlindBoxPanel | 5013401 | 5013402 | 150134 | prefab ไม่มี / icon มี |
รายการนี้ยังไม่อยู่ใน selected preview families ปัจจุบัน กลุ่มที่ assets มีถูกกันไว้เพราะ DisplayItemList และ event-specific data handlers ยังไม่ครบ จึงต้องแยกจากกรณี asset ไม่มีจริง
Exact paths ของสามรายการที่มีข้อมูลใหม่ชัดเจน:
```text
UI/Quest/Widget/QuestMechCraftPanel.prefab
UI/Quest/Widget/QuestComicDessertPanel.prefab
UI/Quest/Widget/QuestRealityShowPanel.prefab
```
BlindBox แถวที่ capture ได้เก็บ path `Assets/AsbRes/UI/Quest/Widget/QuestBlindBoxPanel.prefab` ซึ่ง `AssetMgr.Exists` ให้ false อย่าเดาว่าถอด prefix หรือเปลี่ยน case แล้วจะใช้งานได้ ต้องตรวจ canonical loader/path ก่อน
### เงื่อนไขที่อยู่ในแถวจริง
| Panel | UnlockConditions | FinishConditions ที่ต้องตามต่อ |
| --- | --- | --- |
| 50132 MechCraft | `[PlayerLevel:21]` | QuestClose ของ 6088098–6088120 ทุก ID ในช่วง |
| 50142 ComicDessert | `[PlayerLevel:21]` | QuestClose ของ 6090001–6090005 และ 6090014 |
| 50143 RealityShow | `[PlayerLevel:21]` | QuestClose ของ 6091004, 6091008, 6091012, 6091016, 6091020, 6091001, 6091005, 6091009, 6091013, 6091017 |
| 50134 BlindBox | `[PlayerLevel:4]` | `[QuestClose:6089009]` |
อย่า complete quest เหล่านี้ทั้งหมดเพื่อให้หน้าเปิด เพราะบางตัวเป็น **FinishConditions** ซึ่งอาจทำให้หน้าถูกถือว่าจบหรือหายไปแทน ต้องอ่าน semantic ของ condition checker และตรงกับ state จริงก่อน
### TextID สำหรับ resolve ชื่อหน้าจอแบบ targeted
| Panel | TabName.hash | TabName.hash64 |
| --- | ---: | ---: |
| 50132 | 1880458566 | 6958762709850968366 |
| 50142 | -2011224203 | 143653261616862737 |
| 50143 | -2011224202 | 14823125606058724992 |
| 50134 | 1880458564 | 7162233255424057948 |
raw capture รักษา integer strings เดิมไว้ เลข hash64 หลายตัวเกิน exact integer range ของ JavaScript Number ห้าม parse แล้ว serialize ด้วย Number จนค่าเปลี่ยน ใช้ parser ที่รักษา int64/uint64 หรือเก็บเป็น string สำหรับ derived exports
## 4. ID mapping ของ schedule ต้องไม่สลับ
ใน `internal/gameserver/handlers_challenge.go` handler `GetActivityScheduleConfig` ส่ง:
```text
ActivityScheduleData.ActivityId = ActivityModuleID
ActivityScheduleData.PanelId = ActivityPanelID
```
ตัวอย่าง MechCraft ตาม association ที่ capture มา:
```text
ActivityConfig.ActivityID = 50132
ActivityConfig.ActivityPanelID = 50132
ActivityConfig.ActivityModuleIDList = [5013201]
ActivityConfig.ResidentModuleList = [5013202]
```
อย่าเอา `50132` ไปส่งเป็น module schedule แทน `5013201` เพียงเพราะ field ใน wire ชื่อ ActivityId การมี resident module ก็ไม่ได้พิสูจน์ว่าใช้เป็น active preview แบบเดียวกับ main module ได้ ต้องตรวจ proxy/phase behavior ของกิจกรรมนั้น
`ActivityPanelID=0` บางแถวต้อง resolve ตาม Client behavior ที่ตรวจไว้ โดย loader ปัจจุบันใช้ fallback ActivityID แต่มี 99 activities ที่ยังไม่มี panel row ให้ match ใน capture นี้ อย่าส่งทุกแถวพร้อม panel 0 หรือสร้าง panel ID ขึ้นเอง
หลาย rerun activities อ้าง module เดียวกัน เช่น module 1002101 ถูกใช้กับ panel 10021/10113 ซึ่งเป็น prefab/handler เดียวกัน ปัจจุบันรวมเหลือรายการเดียวแบบ deterministic ถ้าเปลี่ยน policy แล้วพบต่าง prefab/handler loader จะ error แทนการเลือกแถวแรก
## 5. คำตอบ/data handlers ที่มีจริง กับที่ยังไม่มี
`internal/gameserver/handlers_activity_preview.go` มี:
- `GetMultipleDropInfo`: สร้าง explicit panel entries แต่ counter เป็นศูนย์ เป็น preview ไม่ใช่แจก quota/reward เพิ่ม
- `GetActiveActivityData`: มี handler แต่ policy ปัจจุบันไม่เปิด family ที่เคยเกิด invalid-item error กลับมา
- `GetFiveDimMiniGameData`: ยังตอบ list ว่าง ไม่ใช่ implementation ของ Stella Jump/gameplay
- `QuestState`: เป็นชื่อ policy grouping ที่อาศัย quest/mission handlers เดิม ไม่ใช่ generic handler ที่ทำ MechCraft/RealityShow ทุกระบบได้
ปัจจุบันยังไม่มีการพิสูจน์ event-specific data/entry callbacks ครบสำหรับ MechCraft, ComicDessert และ RealityShow อย่าส่ง null success response หรือ advertise ก่อนรู้ว่า Client จะขอ state อะไรต่อ
ตาราง CmdID ใน `protocol/proto/upstream_cmdids.go` ระบุ:
```text
Source: https://git.xeondev.com/HonkaiSlopRail/pearl-sr protocol/src/root.zig
Revision: 005d2c12db4781071f4b5b68e8f364587886a710
```
มีชื่อชัดเจนบางระบบ เช่น `PixAirGetData`, `GetChenLingFesData`, `StartFinalityBattleLevel`, `BlindBoxGetData` แต่การมีชื่อในตารางยังไม่ใช่หลักฐานว่า handler ใช้งานครบ และ MechCraft/ComicDessert/RealityShow ยังไม่พบชื่อชัดเจนจากการค้นนี้ อาจยังใช้ obfuscated names ต้องผูกจาก sender/callback schema จริง ห้ามเดา aliases หรือใช้เลขหลาย revision
## 6. ไปหาต่อจากไหนโดยไม่สแกนทั้ง assembly
### หลักฐาน named tables ที่มีแล้ว
`tools/preview_catalog_metadata.lua` ตรวจเฉพาะชื่อ type และ `FromBinary` ของ ActivityPanelRow/ActivityConfigRow แล้วนำไปตาม flat dictionary chain
`tools/preview_flat_tables.js` มี exact getter chain ของ assembly hash ข้างต้น:
| ตาราง | GetAll RVA สำหรับ hash ที่ระบุเท่านั้น |
| --- | --- |
| ActivityPanelRow | `0x1e4ca860` |
| ActivityConfigRow | `0x1dfbc4d0` |
getter traces อยู่ใน `battle_diagnostics/preview-activity-getter.asm`, `preview-panels-getter.asm` พร้อม `preview-activity-{loader,add}.asm` และ `preview-activity-panel-{loader,add}.asm`
Capture อ่านครั้งละ 16 แถวต่อ managed marker และตรวจ bounds ก่อน serialize ไม่ต้องเรียก scene/level factory `tools/preview_capture_trigger.lua` ส่ง marker `GAC_PREVIEW_TICK` แบบจำกัดครั้งและ pause ใน Battle
**ข้อมูลถูก capture แล้ว ไม่จำเป็นต้องติด probe ซ้ำเพียงเพื่อเปิดดูตารางเดิม** หากต้องอ่านใหม่ต้องตรวจ process/module hash ใหม่ก่อน RVA เป็นของ shipped binary เฉพาะรุ่น ไม่ใช่ production constants และ MethodHandle/pointer เก่าห้ามใช้ข้าม process
### จุดเริ่ม event page/proxy
จาก named metadata ของ `RPG.Client.ActivityModule` พบ:
```text
ActivityDataDict
ActivityPanelDataContainer
CustomizedPanelDataContainer
_PanelDataProxyFactory
_PanelID2TemplateIndexLUT
_PanelTemplates
_AvailablePanelDatas
_phaseMap / _phaseList
GetActivityData(UInt32)
_OnScheduleConfigRefresh(System.Object)
```
ข้อมูลนี้ใช้เลือก inspect object/proxy ของ **panel ID เป้าหมาย** ได้ ไม่ต้อง enumerate ทุก type ใน assembly
สำหรับ panel UI ให้ตาม prefab/binder registration ของ technical name ที่ระบุข้างบน เพื่อหา exact loaded Lua module/controller ก่อน เมื่อมี module name ที่ยืนยันแล้วค่อยอ่าน named functions/upvalues หรือ loader bytes ไม่สมมติ callback ชื่อ `_refresh`/`GetData` ว่าแต่ละ panel เหมือนกันหมด
มีตัวอย่างวิธีอ่าน Luau โดยไม่ execute closure ใน `tools/gacha_load_only.lua` และ bytecode reader `tools/inspect_luau_v4.py` สำหรับ GachaMainPage ที่ทำไว้ก่อน **ใช้เป็นรูปแบบการวิเคราะห์เท่านั้น** อย่า require/reload event controller หรือใช้ package loader ของชื่อที่เดาขึ้นเองระหว่าง gameplay
## 7. ลำดับงานที่แนะนำ
1. เปิด `derived/event-index.json`/CSV แล้วค้น panel 50132/50142/50143 ก่อน จะเห็น association, reward item IDs และ conditions โดยไม่ต้อง extract ใหม่
2. Resolve TabName/TitleName/IntroDesc จาก TextID ที่เจาะจง เพื่อบอกผู้ใช้ได้ว่า technical event นี้ตรงกับชื่อใดจริง
3. อ่าน exact UI controller/data proxy ของ panel หนึ่งระบบให้ครบ entry → data request → initialization → close/return map โดยไม่ execute action ระหว่างสำรวจ
4. ตรวจ display-item dependencies ทุก ID กับ current Client item assets/config และดูว่า reward preview สร้าง ItemData ได้จริงก่อนแสดงหน้า
5. ผูก main/resident modules และ early access state จาก schema ปัจจุบัน ไม่ตีความทุก module เป็น active event ชนิดเดียวกัน
6. Implement data/entry path ของระบบนั้นแล้วค่อยขยาย policy และ schedule อย่าเปิดทุก prefab ที่มีแล้วตอบว่าง
7. อัปเดตสถานะแยก asset present / source implemented / deployed / Client confirmed คำว่า “หาเจอ” ไม่ใช่คำว่า “เล่นได้แล้ว”
### ข้อจำกัดที่ยังเหลือ
- ยังไม่มี export official per-event active schedule ชุดปัจจุบันจาก Client/service ต้นทาง เวลาใน server ใช้ operator `cfg.ActivitySchedule` ร่วมกับ Endgame
- ยังไม่มี localized titles ที่ resolve ครบทุก panel
- raw catalog นี้ไม่รวมทุก event gameplay table, Lua/controller, stage/reward graph หรือ asset bundle ทั้งเกม
- เอกสารนี้ไม่ยืนยันว่า UI ใหม่เปิดได้หรือจอดำหาย ผู้ใช้ไม่ต้องถูกวนให้ลองทีละ handler ตามคำสั่งล่าสุด
ดังนั้นให้ใช้รายการนี้ช่วย GLM หา event และต่อข้อมูลที่ยังขาด แทนการสรุปว่า Beta นี้ไม่มี event เพราะชื่อ type หนึ่งหาไม่เจอ