175 lines
5.9 KiB
Go
175 lines
5.9 KiB
Go
package catalogs
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
)
|
||
|
||
var _ = json.RawMessage{}
|
||
var _ = sync.Mutex{}
|
||
var _ = os.ReadFile
|
||
var _ = filepath.Join
|
||
|
||
type ScenePresetEntry4229938 struct {
|
||
Key string `json:"key"`
|
||
Label string `json:"label"`
|
||
RaidId uint32 `json:"raidId"`
|
||
InstanceId uint64 `json:"instanceId"`
|
||
UniverseId uint32 `json:"universeId"`
|
||
X float32 `json:"x"`
|
||
Y float32 `json:"y"`
|
||
Z float32 `json:"z"`
|
||
Facing float32 `json:"facing"`
|
||
}
|
||
|
||
//
|
||
// 一条 MapentranceConfig 的入口级投影(2026-09-27 新增,供地图入口四连发用)。
|
||
// 与 ScenePresetEntry4229938 的区别:那份是「按 raid 挑一个落点」的传送预设,
|
||
// Key 是字符串,入口 id 已经丢了;这份保留 Id 与 Type,
|
||
// 因为 SyncMapEntrance / UpdateMapEntrance / SyncPrepareMapEntrance 三帧推的都是
|
||
// 入口 id,而 Type == 11 是「这是地铁站」的唯一判据。
|
||
// 2026-09-30 追加 5 个 Jiguan* 字段(景点 / 电梯传送门,Type == 1):
|
||
// 客户端 RpcUtils.AskEnterRaidByMapEntrance 只把 Coordinate 当 beforePosition、
|
||
// JiguanStartTimeline/JiguanEndTimeline 当动画名发上来,目的地靠服务端给
|
||
// (JiguanTeleportPos 是 Spoon 航点 id,本地没有 Spoon 数据)。
|
||
// 目的地坐标的推导见 JiguanElevatorCatalog4229938。
|
||
// ⛔ 曾经是 15 个位置参数的 positional record;改成 init 属性只是因为单点构造时
|
||
// 15 个同型参数(uint/float/string 混排)太容易写错位。
|
||
//
|
||
type MapEntranceEntry4229938 struct {
|
||
Id uint32 `json:"id"`
|
||
RaidId uint32 `json:"raidId"`
|
||
Type uint32 `json:"type"`
|
||
Name string `json:"name"`
|
||
InstanceId uint64 `json:"instanceId"`
|
||
UniverseId uint32 `json:"universeId"`
|
||
X float32 `json:"x"`
|
||
Y float32 `json:"y"`
|
||
Z float32 `json:"z"`
|
||
Facing float32 `json:"facing"`
|
||
//
|
||
// MapentranceConfig.JiguanTeleportPos —— 目的地 Spoon 航点 id(如 1917305)。
|
||
// 0 = 这条入口没有 Jiguan 目的地(326/327 这类只有 JiguanTeleportPosName 的行)。
|
||
//
|
||
JiguanTeleportPos uint32 `json:"jiguanTeleportPos"`
|
||
// MapentranceConfig.JiguanTeleportPosName —— 目的地的 Spoon 航点名字(只用于日志)。
|
||
JiguanTeleportPosName string `json:"jiguanTeleportPosName"`
|
||
// MapentranceConfig.JiguanRaidID —— 目的地 raid;实测与 RaidId 恒等。
|
||
JiguanRaidId uint32 `json:"jiguanRaidId"`
|
||
// MapentranceConfig.JiguanStartTimeline(如 loading_elevator02)—— 过场前动画。
|
||
JiguanStartTimeline string `json:"jiguanStartTimeline"`
|
||
// MapentranceConfig.JiguanEndTimeline(如 loading_general_end)—— 过场后动画。
|
||
JiguanEndTimeline string `json:"jiguanEndTimeline"`
|
||
// MapentranceConfig.Type == 1:景点 / 电梯传送门(93 行里 45 行)。
|
||
IsJiguan bool `json:"isJiguan"`
|
||
}
|
||
|
||
//
|
||
// Scene ("raid") preset catalog built from the game dumps:
|
||
// RaidConfig.json (raid → SceneId = instance id, Multiverse = universe id) and
|
||
// MapentranceConfig.json (entrance → RaidId + Coordinate/MapTeleportPos + facing).
|
||
// Verified: Nova raid 23300888 → scene/instance 20001222, Lingyun 23300999 → 20001223.
|
||
//
|
||
const (
|
||
// MapentranceConfig.Type = 地铁站(93 行里 25 行)。
|
||
SceneCatalog4229938_MapEntranceTypeSubway uint32 = 11
|
||
//
|
||
// MapentranceConfig.Type = 景点 / 电梯传送门(93 行里 45 行,其中 41 行带 JiguanTeleportPos)。
|
||
// 客户端走 RpcUtils.AskEnterRaidByMapEntrance → AskEnterRaidByMapEntrance(63510026)。
|
||
//
|
||
SceneCatalog4229938_MapEntranceTypeJiguan uint32 = 1
|
||
)
|
||
|
||
var (
|
||
SceneCatalog4229938_cacheLock sync.RWMutex
|
||
SceneCatalog4229938_cached = false
|
||
SceneCatalog4229938_entries []any
|
||
)
|
||
|
||
// LoadSceneCatalog4229938 loads catalog records from client config directory
|
||
func LoadSceneCatalog4229938(configDir string) ([]any, error) {
|
||
SceneCatalog4229938_cacheLock.RLock()
|
||
if SceneCatalog4229938_cached {
|
||
defer SceneCatalog4229938_cacheLock.RUnlock()
|
||
return SceneCatalog4229938_entries, nil
|
||
}
|
||
SceneCatalog4229938_cacheLock.RUnlock()
|
||
|
||
SceneCatalog4229938_cacheLock.Lock()
|
||
defer SceneCatalog4229938_cacheLock.Unlock()
|
||
if SceneCatalog4229938_cached { return SceneCatalog4229938_entries, nil }
|
||
|
||
filePath := filepath.Join(configDir, "SceneCatalog.json.json")
|
||
data, err := os.ReadFile(filePath)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var raw struct {
|
||
Records []json.RawMessage `json:"records"`
|
||
}
|
||
if err := json.Unmarshal(data, &raw); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var result []any
|
||
for _, item := range raw.Records {
|
||
var m map[string]any
|
||
if err := json.Unmarshal(item, &m); err == nil {
|
||
result = append(result, m)
|
||
}
|
||
}
|
||
|
||
SceneCatalog4229938_entries = result
|
||
SceneCatalog4229938_cached = true
|
||
return result, nil
|
||
}
|
||
|
||
func SceneCatalog4229938_LoadRaidIds() []uint32 {
|
||
// Catalog helper SceneCatalog4229938_LoadRaidIds
|
||
return nil
|
||
}
|
||
|
||
func SceneCatalog4229938_LoadSceneIds() []uint32 {
|
||
// Catalog helper SceneCatalog4229938_LoadSceneIds
|
||
return nil
|
||
}
|
||
|
||
func SceneCatalog4229938_TryGetByRaid(raidId uint32, preset ScenePresetEntry4229938) bool {
|
||
// Catalog helper SceneCatalog4229938_TryGetByRaid
|
||
return false
|
||
}
|
||
|
||
//
|
||
// 入口级投影:保留 Id / Type,坐标优先级与 Load 完全一致
|
||
// (MapTeleportPos 优先,回退 Coordinate),这样「点同一个入口」与
|
||
// 「GM 面板按 raid 传送」落在同一个点。
|
||
//
|
||
func SceneCatalog4229938_LoadMapEntrances() []MapEntranceEntry4229938 {
|
||
// Catalog helper SceneCatalog4229938_LoadMapEntrances
|
||
return nil
|
||
}
|
||
|
||
func SceneCatalog4229938_LoadRecords(path string) []any {
|
||
// Catalog helper SceneCatalog4229938_LoadRecords
|
||
return nil
|
||
}
|
||
|
||
//
|
||
// 可选 u32 字段。先判 JsonValueKind.Number ——
|
||
// TryGetUInt32 遇到字符串/对象会抛异常(硬规则 195),不是返回 false。
|
||
//
|
||
func SceneCatalog4229938_U32(row any, key string) uint32 {
|
||
// Catalog helper SceneCatalog4229938_U32
|
||
return 0
|
||
}
|
||
|
||
// 可选字符串字段;缺失 / 类型不对一律空串。
|
||
func SceneCatalog4229938_Str(row any, key string) string {
|
||
// Catalog helper SceneCatalog4229938_Str
|
||
return ""
|
||
}
|
||
|