fix(scene): unlock teleport pillars on maps missing from mapDefaultEntranceMap
The user report: pillars visible on the map but locked, and clicking a teleport does nothing (client never sends EnterScene). Root cause: mapDefaultEntranceMap covers only 115 of 371 floors - the GetSceneMapInfo reply had no unlocked teleports for the missing floors (mostly new-region 2xxxxx maps), so the client locked the pillars and never initiated the teleport. - findEntryForFloor: resolve entry by searching config names P*_F<floor> directly, with mapDefaultEntranceMap as the first chance - GetSceneMapInfo: use the new resolver and merge teleports.json keys into unlocked_teleport_list for every floor - EnterScene: floor ids resolve through the same path; a teleport id arriving via scene_identifier (MDAIDPPKOPO.PLIDNBMCIJH) now also resolves the destination entry - loadScene: exact teleport position from teleports.json when the res config has no inline teleport with that id
This commit is contained in:
1 parent
72861c3028
commit
d364b9616f
4 files changed
+90
-12
No files matched your search
@@ -2,3 +2,4 @@
|
||||
gameserver.log
|
||||
server_debug.log
|
||||
*.log
|
||||
*.exe~
|
||||
@@ -120,12 +120,18 @@ func init() {
|
||||
switch {
|
||||
case req.EntryId != 0 && mapHasEntry(res, req.EntryId):
|
||||
resolvedEntry = req.EntryId
|
||||
case sceneIdent != nil && res.MapDefaultEntranceMap[sceneIdent.FloorId] != 0:
|
||||
resolvedEntry = res.MapDefaultEntranceMap[sceneIdent.FloorId]
|
||||
case res.MapDefaultEntranceMap[req.EntryId] != 0:
|
||||
resolvedEntry = res.MapDefaultEntranceMap[req.EntryId]
|
||||
case sceneIdent != nil && sceneIdent.FloorId != 0:
|
||||
resolvedEntry = findEntryForFloor(res, sceneIdent.FloorId)
|
||||
case req.EntryId != 0 && findEntryForFloor(res, req.EntryId) != 0:
|
||||
// req.EntryId doubles as a floor id in some map flows
|
||||
resolvedEntry = findEntryForFloor(res, req.EntryId)
|
||||
case req.TeleportId != 0:
|
||||
resolvedEntry = findEntryByTeleport(res, req.TeleportId, currentEntry())
|
||||
case sceneIdent != nil && sceneIdent.TeleportNigger != nil:
|
||||
if t, okc := sceneIdent.TeleportNigger.(*goproto.SceneIdentifier_MDAIDPPKOPO); okc && t.MDAIDPPKOPO != nil && t.MDAIDPPKOPO.PLIDNBMCIJH != 0 {
|
||||
// map teleport click: teleport id arrives via scene_identifier
|
||||
resolvedEntry = findEntryByTeleport(res, t.MDAIDPPKOPO.PLIDNBMCIJH, currentEntry())
|
||||
}
|
||||
case interactID != 0:
|
||||
resolvedEntry = findEntryByInteract(res, interactID, currentEntry())
|
||||
default:
|
||||
@@ -233,7 +239,10 @@ func init() {
|
||||
&goproto.ChestInfo{ChestType: goproto.ChestType_MAP_INFO_CHEST_TYPE_PUZZLE},
|
||||
)
|
||||
|
||||
if entryID := res.MapDefaultEntranceMap[floorID]; entryID != 0 {
|
||||
// resolve the floor's entry directly (mapDefaultEntranceMap covers
|
||||
// only 115/371 floors - new-region maps were left with no unlocked
|
||||
// teleports, which locked the pillars)
|
||||
if entryID := findEntryForFloor(res, floorID); entryID != 0 {
|
||||
if _, cfg, ok := firstSceneOfEntry(res, entryID); ok {
|
||||
groupIDs := sortedU32Keys2(cfg.Scenes)
|
||||
for _, groupID := range groupIDs {
|
||||
@@ -258,6 +267,20 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// teleports.json covers every map (incl. floors whose res config
|
||||
// has no inline teleports)
|
||||
if m := common.Teleports()[floorID]; m != nil {
|
||||
seen := map[uint32]bool{}
|
||||
for _, t := range mapInfo.UnlockedTeleportList {
|
||||
seen[t] = true
|
||||
}
|
||||
for id := range m {
|
||||
if id != 0 && !seen[id] {
|
||||
mapInfo.UnlockedTeleportList = append(mapInfo.UnlockedTeleportList, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rsp.SceneMapInfo = append(rsp.SceneMapInfo, mapInfo)
|
||||
}
|
||||
return nil
|
||||
@@ -366,12 +389,40 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// findEntryForFloor resolves an entry id for a floor WITHOUT relying on
|
||||
// mapDefaultEntranceMap (which misses 287/371 floors): search the config
|
||||
// names "P<plane>_F<floor>" directly.
|
||||
func findEntryForFloor(res *common.JsonConfig, floorID uint32) uint32 {
|
||||
if entryID := res.MapDefaultEntranceMap[floorID]; entryID != 0 {
|
||||
return entryID
|
||||
}
|
||||
suffix := fmt.Sprintf("_F%d", floorID)
|
||||
entryIDs := sortedU32Keys2(res.LevelOutputConfigs)
|
||||
for _, eid := range entryIDs {
|
||||
for name := range res.LevelOutputConfigs[eid] {
|
||||
if len(name) > len(suffix) && name[len(name)-len(suffix):] == suffix {
|
||||
return eid
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func mapHasEntry(res *common.JsonConfig, entryID uint32) bool {
|
||||
_, ok := res.LevelOutputConfigs[entryID]
|
||||
return ok
|
||||
}
|
||||
|
||||
func findEntryByTeleport(res *common.JsonConfig, teleportID uint32, fallback uint32) uint32 {
|
||||
// teleports.json covers floors whose res config has no inline teleports:
|
||||
// teleport id -> floor -> entry (via the floor name search)
|
||||
for floorID, m := range common.Teleports() {
|
||||
if _, ok := m[teleportID]; ok {
|
||||
if entry := findEntryForFloor(res, floorID); entry != 0 {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
}
|
||||
entryIDs := sortedU32Keys2(res.LevelOutputConfigs)
|
||||
for _, eid := range entryIDs {
|
||||
names := make([]string, 0, len(res.LevelOutputConfigs[eid]))
|
||||
@@ -459,6 +510,16 @@ func loadScene(s *Session, entryID uint32, isEnterScene bool, teleportID *uint32
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// exact teleport from teleports.json (covers floors whose res
|
||||
// config has no inline teleports)
|
||||
if m := common.Teleports()[floorID]; m != nil {
|
||||
if tp, ok := m[*teleportID]; ok {
|
||||
jsonPos.X, jsonPos.Y, jsonPos.Z, jsonPos.RotY = tp.Pos.X, tp.Pos.Y, tp.Pos.Z, tp.Rot.Y
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found && len(groupIDs) > 0 {
|
||||
// first teleport of the first group that has one
|
||||
for _, gid := range groupIDs {
|
||||
|
||||
+7
-7
@@ -6,15 +6,15 @@
|
||||
"3": 1004
|
||||
},
|
||||
"position": {
|
||||
"x": -92,
|
||||
"y": 4278,
|
||||
"z": 68083,
|
||||
"rot_y": 155566
|
||||
"x": 780,
|
||||
"y": -153008,
|
||||
"z": -621450,
|
||||
"rot_y": 0
|
||||
},
|
||||
"scene": {
|
||||
"plane_id": 10202,
|
||||
"floor_id": 10202001,
|
||||
"entry_id": 102020107
|
||||
"plane_id": 30141,
|
||||
"floor_id": 30141001,
|
||||
"entry_id": 3014101
|
||||
},
|
||||
"main_character": "FemaleHarmony",
|
||||
"march_type": "MarchHunt",
|
||||
|
||||
@@ -47,3 +47,19 @@
|
||||
1. **ทดสอบกับ client จริง** — เปิด `run_go.bat` (GaC-hkrpg-go) แล้ว login ด้วย hosts/proxy เดิม
|
||||
2. Gacha handlers ถูก skip (proto 4.6.51 เปลี่ยนชื่อ GetGachaInfoCsReq/DoGachaCsReq) — หาชื่อใหม่จาก dump
|
||||
3. ถ้า client ฟ้อง cmd ไหน "Unknown" ให้เช็ค `gameserver.log` แล้วเติม handler ในตัว Go
|
||||
|
||||
## เพิ่มเติม (รอบแก้เสาวาป — 01:3x)
|
||||
|
||||
**อาการ:** เสาวาปในแมพใหม่ๆ มองเห็นในแมพแต่ไม่เปิด + กดวาปไม่ไป (client ไม่ส่ง EnterScene เลย)
|
||||
|
||||
**ต้นเหตุ:** `mapDefaultEntranceMap` ใน res.json ครอบคลุมแค่ 115/371 ฟลอร์ — โค้ด GetSceneMapInfo
|
||||
และ EnterScene resolution พึ่งมันทั้งคู่ ฟลอร์ที่ไม่อยู่ในนี้ = ไม่มีรายชื่อเสาปลดล็อคส่งกลับ
|
||||
→ client ล็อคเสา และไม่เริ่มวาป
|
||||
|
||||
**แก้ (commit 0fdadd0):**
|
||||
- `findEntryForFloor` — หา entry จากชื่อ config `P*_F<floor>` โดยตรง (mapDefaultEntranceMap เป็น first chance)
|
||||
- GetSceneMapInfo รวมรายชื่อเสาจาก teleports.json ทุกฟลอร์
|
||||
- EnterScene: teleport id ผ่าน scene_identifier (MDAIDPPKOPO.PLIDNBMCIJH) resolve ปลายทางได้
|
||||
- loadScene: ใช้ตำแหน่ง teleport จาก teleports.json ตรงๆ ถ้า res ไม่มี id นั้น
|
||||
|
||||
**บทเรียน:** data index บางตัวใน res.json ไม่ครอบคลุมทุกแมพ — ต้องมี fallback ค้นจากชื่อ config / teleports.json เสมอ
|
||||
Reference in new issue
Block a user