# ข้อมูลกิจกรรม 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 หนึ่งหาไม่เจอ