fix(scene): unlock all teleports across maps, merge resource configs, fix scenary not load error, and add quick farm battle handlers
This commit is contained in:
1 parent
9aab62414f
commit
163d4433e6
47 files changed
+2025067
-6082
No files matched your search
@@ -20,16 +20,36 @@ import (
|
||||
// Rust iterated a HashMap arbitrarily; we pick the lexicographically first
|
||||
// name for determinism.
|
||||
func firstSceneOfEntry(res *common.JsonConfig, entryID uint32) (string, *common.LevelOutputConfig, bool) {
|
||||
m, ok := res.LevelOutputConfigs[entryID]
|
||||
if !ok || len(m) == 0 {
|
||||
return "", nil, false
|
||||
if m, ok := res.LevelOutputConfigs[entryID]; ok && len(m) > 0 {
|
||||
names := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names[0], m[names[0]], true
|
||||
}
|
||||
names := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
names = append(names, k)
|
||||
if entryID != 0 {
|
||||
name := fmt.Sprintf("P%d_F%d", entryID/100, entryID*10+1)
|
||||
cfg := &common.LevelOutputConfig{
|
||||
IsEnteredSceneInfo: true,
|
||||
Scenes: map[uint32]common.SceneData{
|
||||
1: {
|
||||
Teleports: map[uint32]common.TeleportInfo{
|
||||
entryID: {Pos: common.Vector{X: 0, Y: 0, Z: 0}},
|
||||
1: {Pos: common.Vector{X: 0, Y: 0, Z: 0}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if res.LevelOutputConfigs == nil {
|
||||
res.LevelOutputConfigs = map[uint32]map[string]*common.LevelOutputConfig{}
|
||||
}
|
||||
res.LevelOutputConfigs[entryID] = map[string]*common.LevelOutputConfig{
|
||||
name: cfg,
|
||||
}
|
||||
return name, cfg, true
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names[0], m[names[0]], true
|
||||
return "", nil, false
|
||||
}
|
||||
|
||||
// parsePlaneFloor splits "P<plane>_F<floor>".
|
||||
@@ -65,19 +85,24 @@ func init() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// recover from a stale challenge arena back to the Parlor Car
|
||||
// recover from a stale challenge arena, broken map, or void coordinate back to Belobog Admin District
|
||||
entryID := player.Scene.EntryID
|
||||
if entryID >= 3000000 && entryID < 4000000 {
|
||||
entryID = 100000104
|
||||
if (entryID >= 3000000 && entryID < 4000000) || entryID == 100000104 || entryID == 100000304 || entryID == 1030402 || entryID == 0 || player.Position.Y < -50000 {
|
||||
entryID = 102020107
|
||||
player.Scene.EntryID = 102020107
|
||||
player.Scene.PlaneID = 10202
|
||||
player.Scene.FloorID = 10202001
|
||||
player.Position = common.Position{X: -92, Y: 4278, Z: 68083, RotY: 155566}
|
||||
player.SavePersistent()
|
||||
}
|
||||
|
||||
defaultScene := &goproto.SceneInfo{
|
||||
GameModeType: 1,
|
||||
EntryId: entryID,
|
||||
}
|
||||
if entryID == 100000104 {
|
||||
defaultScene.PlaneId = 10000
|
||||
defaultScene.FloorId = 10000000
|
||||
if entryID == 102020107 {
|
||||
defaultScene.PlaneId = 10202
|
||||
defaultScene.FloorId = 10202001
|
||||
} else {
|
||||
defaultScene.PlaneId = player.Scene.PlaneID
|
||||
defaultScene.FloorId = player.Scene.FloorID
|
||||
@@ -103,10 +128,10 @@ func init() {
|
||||
}
|
||||
player := s.JSON()
|
||||
currentEntry := func() uint32 {
|
||||
if player != nil {
|
||||
if player != nil && player.Scene.EntryID != 0 && player.Scene.EntryID != 100000104 && player.Scene.EntryID != 100000304 {
|
||||
return player.Scene.EntryID
|
||||
}
|
||||
return 100000104
|
||||
return 102020107
|
||||
}
|
||||
|
||||
interactID := uint32(req.InteractId)
|
||||
@@ -115,17 +140,17 @@ func init() {
|
||||
sceneIdent = proto.Clone(req.SceneIdentifier).(*goproto.SceneIdentifier)
|
||||
}
|
||||
|
||||
// resolve target entry (mirrors the Rust resolution chain)
|
||||
// resolve target entry (mirrors the Rust resolution chain, with cascading fallbacks)
|
||||
resolvedEntry := uint32(0)
|
||||
switch {
|
||||
case req.EntryId != 0 && mapHasEntry(res, req.EntryId):
|
||||
if req.EntryId != 0 && mapHasEntry(res, req.EntryId) {
|
||||
resolvedEntry = req.EntryId
|
||||
case sceneIdent != nil && sceneIdent.FloorId != 0:
|
||||
} else if 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
|
||||
}
|
||||
if resolvedEntry == 0 && req.EntryId != 0 {
|
||||
resolvedEntry = findEntryForFloor(res, req.EntryId)
|
||||
case req.TeleportId != 0:
|
||||
}
|
||||
if resolvedEntry == 0 && req.TeleportId != 0 {
|
||||
floorID := uint32(0)
|
||||
if sceneIdent != nil {
|
||||
floorID = sceneIdent.FloorId
|
||||
@@ -133,21 +158,26 @@ func init() {
|
||||
if entry := findEntryByTeleportInFloor(res, req.TeleportId, floorID); entry != 0 {
|
||||
resolvedEntry = entry
|
||||
} else {
|
||||
resolvedEntry = findEntryByTeleport(res, req.TeleportId, currentEntry())
|
||||
resolvedEntry = findEntryByTeleport(res, req.TeleportId, 0)
|
||||
}
|
||||
case sceneIdent != nil && sceneIdent.TeleportNigger != nil:
|
||||
}
|
||||
if resolvedEntry == 0 && 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 + floor arrive via scene_identifier
|
||||
tpID := t.MDAIDPPKOPO.PLIDNBMCIJH
|
||||
if entry := findEntryByTeleportInFloor(res, tpID, sceneIdent.FloorId); entry != 0 {
|
||||
resolvedEntry = entry
|
||||
} else {
|
||||
resolvedEntry = findEntryByTeleport(res, tpID, currentEntry())
|
||||
resolvedEntry = findEntryByTeleport(res, tpID, 0)
|
||||
}
|
||||
}
|
||||
case interactID != 0:
|
||||
resolvedEntry = findEntryByInteract(res, interactID, currentEntry())
|
||||
default:
|
||||
}
|
||||
if resolvedEntry == 0 && interactID != 0 {
|
||||
resolvedEntry = findEntryByInteract(res, interactID, 0)
|
||||
}
|
||||
if resolvedEntry == 0 && req.EntryId != 0 {
|
||||
resolvedEntry = req.EntryId
|
||||
}
|
||||
if resolvedEntry == 0 {
|
||||
resolvedEntry = currentEntry()
|
||||
}
|
||||
|
||||
@@ -215,6 +245,10 @@ func init() {
|
||||
// a wrong state (like 1100) breaks interactions and UI entry points
|
||||
state := uint32(1)
|
||||
if p, ok := s.PropEntities[req.PropEntityId]; ok {
|
||||
if p.State == 0 {
|
||||
p.State = 1
|
||||
s.PropEntities[req.PropEntityId] = p
|
||||
}
|
||||
state = p.State
|
||||
}
|
||||
|
||||
@@ -354,7 +388,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
player.SavePersistent()
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -396,31 +429,106 @@ func init() {
|
||||
// cmd 1432 -> 1421: unlock every teleport in the game
|
||||
handle("GetUnlockTeleport", func(s *Session, req *goproto.GetUnlockTeleportCsReq, rsp *goproto.GetUnlockTeleportScRsp) error {
|
||||
rsp.Retcode = 0
|
||||
unlocks := getMissionUnlocks()
|
||||
seen := map[uint32]bool{}
|
||||
var tps []uint32
|
||||
|
||||
// 1. All IDs from mission_unlocks.json
|
||||
unlocks := getMissionUnlocks()
|
||||
for _, id := range unlocks.TeleportIDs {
|
||||
if id != 0 && !seen[id] {
|
||||
seen[id] = true
|
||||
tps = append(tps, id)
|
||||
}
|
||||
}
|
||||
if len(tps) == 0 {
|
||||
for _, m := range common.Teleports() {
|
||||
for id := range m {
|
||||
if id != 0 && !seen[id] {
|
||||
seen[id] = true
|
||||
tps = append(tps, id)
|
||||
|
||||
// 2. All IDs from teleports DB across all floors
|
||||
for _, m := range common.Teleports() {
|
||||
for id := range m {
|
||||
if id != 0 && !seen[id] {
|
||||
seen[id] = true
|
||||
tps = append(tps, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. All teleport IDs from LevelOutputConfigs
|
||||
if res, err := common.GameRes(); err == nil {
|
||||
for _, m := range res.LevelOutputConfigs {
|
||||
for _, cfg := range m {
|
||||
for _, sc := range cfg.Scenes {
|
||||
for tid := range sc.Teleports {
|
||||
if tid != 0 && !seen[tid] {
|
||||
seen[tid] = true
|
||||
tps = append(tps, tid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Any entry IDs requested by client or in EntranceIDs
|
||||
for _, eid := range req.EntryIdList {
|
||||
if eid != 0 && !seen[eid] {
|
||||
seen[eid] = true
|
||||
tps = append(tps, eid)
|
||||
}
|
||||
}
|
||||
for _, id := range unlocks.EntranceIDs {
|
||||
if id != 0 && !seen[id] {
|
||||
seen[id] = true
|
||||
tps = append(tps, id)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(tps, func(i, j int) bool { return tps[i] < tps[j] })
|
||||
rsp.UnlockedTeleportList = tps
|
||||
|
||||
SceneDebugLog("GET_UNLOCK_TELEPORT req_entries=%d teleports_sent=%d", len(req.EntryIdList), len(rsp.UnlockedTeleportList))
|
||||
return nil
|
||||
})
|
||||
|
||||
// cmd 1438 -> 1409: handle entity teleport within scene
|
||||
handle("SceneEntityTeleport", func(s *Session, req *goproto.SceneEntityTeleportCsReq, rsp *goproto.SceneEntityTeleportScRsp) error {
|
||||
rsp.Retcode = 0
|
||||
rsp.EntityMotion = req.EntityMotion
|
||||
if req.EntityMotion != nil && req.EntityMotion.Motion != nil {
|
||||
motion := req.EntityMotion.Motion
|
||||
player := s.JSON()
|
||||
if player != nil {
|
||||
if motion.Pos != nil {
|
||||
player.Position.X = motion.Pos.X
|
||||
player.Position.Y = motion.Pos.Y
|
||||
player.Position.Z = motion.Pos.Z
|
||||
}
|
||||
if motion.Rot != nil {
|
||||
player.Position.RotY = motion.Rot.Y
|
||||
}
|
||||
player.SavePersistent()
|
||||
}
|
||||
}
|
||||
SceneDebugLog("SCENE_ENTITY_TELEPORT entry_id=%d", req.EntryId)
|
||||
return nil
|
||||
})
|
||||
|
||||
// cmd 1267 -> 1263: teleport to mission reset point
|
||||
handle("TeleportToMissionResetPoint", func(s *Session, req *goproto.TeleportToMissionResetPointCsReq, rsp *goproto.TeleportToMissionResetPointScRsp) error {
|
||||
rsp.Retcode = 0
|
||||
player := s.JSON()
|
||||
if player != nil {
|
||||
rsp.Motion = &goproto.MotionInfo{
|
||||
Pos: &goproto.Vector{
|
||||
X: player.Position.X,
|
||||
Y: player.Position.Y,
|
||||
Z: player.Position.Z,
|
||||
},
|
||||
Rot: &goproto.Vector{
|
||||
Y: player.Position.RotY,
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// findEntryForFloor resolves an entry id for a floor WITHOUT relying on
|
||||
|
||||
Reference in new issue
Block a user