198 lines
8.5 KiB
Go
198 lines
8.5 KiB
Go
package catalogs
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
)
|
||
|
||
var _ = json.RawMessage{}
|
||
var _ = sync.Mutex{}
|
||
var _ = os.ReadFile
|
||
var _ = filepath.Join
|
||
|
||
//
|
||
// HouseBuildConfig 的一行 —— 「这栋房子的可装修体」。
|
||
// <para>为什么需要它:HouseConfig.BuildId(0/2/3/4/5)指向本表的 Id,
|
||
// 本表的 IndoorId 才是「房子主体所在的 indoor」,而
|
||
// FurnitureTemplateIds 指向 HouseFurnitureTemplateCatalog4229938
|
||
// 里的**自带家具模板根节点**。整条链:
|
||
// houseId → HouseConfig.BuildId → HouseBuildConfig.FurnitureTemplateIds → 家具树。</para>
|
||
// <para>4 行全表(2026-09-30 核对 E:\ConfigDump\ConfigDump_v3\HouseBuildConfig.json):</para>
|
||
// <code>
|
||
// Id IndoorId Floors FurnitureTemplateIds 对应房子
|
||
// 2 301 1 [14001] 绿屿公馆(11200003)
|
||
// 3 205 1 [10013] 旧物仓公寓(11200004)
|
||
// 4 298 1 [14000] 观澜北岸(11200005)
|
||
// 5 378 2 [13000] 素光小筑(11200006)
|
||
// </code>
|
||
// <para>⛔ IndoorId 与 HouseConfig.GarageIndoorId **不是一回事**:
|
||
// 绿屿公馆两处都写着 301(它的车库就在主体 indoor 里),其余三套
|
||
// IndoorId 是 205/298/378 而 GarageIndoorId 是 300/299/379。
|
||
// 车库这一轮不做,别拿 GarageIndoorId 当 IndoorId 用。</para>
|
||
//
|
||
// HouseBuildConfig.Id,也是客户端 HouseBuildConfig.GetConfig(buildId) 的键。
|
||
// IndoorConfig.Id —— 房子主体 indoor(301/205/298/378)。
|
||
// HouseBuildConfig.Floors,楼层数(1 或 2)。
|
||
// HouseBuildConfig.FurnitureTemplateIds,自带家具模板根 id。
|
||
type HouseBuildDefinition4229938 struct {
|
||
BuildId uint32 `json:"buildId"`
|
||
IndoorId uint32 `json:"indoorId"`
|
||
Floors uint32 `json:"floors"`
|
||
FurnitureTemplateIds []uint32 `json:"furnitureTemplateIds"`
|
||
}
|
||
|
||
//
|
||
// HouseFurnitureTemplateConfig 的一个节点(递归树)。
|
||
// <para>形状:根节点 FurnitureId == 0(纯容器,对应线格式里的
|
||
// IndoorBuildInfo.Root),子节点才是真家具。Position/Rotation 是
|
||
// 绝对世界坐标(不是相对父节点的偏移)—— 绿屿公馆的模板叶子全在
|
||
// (2254..2294, 160.72, 1394..1404),正好是 HouseConfig.11200003.VisitorEntrance 附近。</para>
|
||
// <para>深度:14001(绿屿公馆)是 3 层 —— 147 个叶子里有 9 个是挂在
|
||
// 桌子/柜子下面的小物件(盘子、台灯…),父节点本身也是真家具。其余三个模板都是 2 层。
|
||
// 所以必须递归,不能只取根的直接子节点。</para>
|
||
//
|
||
type HouseFurnitureTemplateNode4229938 struct {
|
||
// HouseFurnitureTemplateConfig.Id(模板内部节点号,10013..14150 量级)。
|
||
NodeId uint32 `json:"nodeId"`
|
||
// HouseFurnitureTemplateConfig.FurnitureId(HouseFurnitureConfig.Id)。0 = 纯容器。
|
||
FurnitureId uint32 `json:"furnitureId"`
|
||
X float32 `json:"x"`
|
||
Y float32 `json:"y"`
|
||
Z float32 `json:"z"`
|
||
RotationX float32 `json:"rotationX"`
|
||
RotationY float32 `json:"rotationY"`
|
||
RotationZ float32 `json:"rotationZ"`
|
||
Children []HouseFurnitureTemplateNode4229938 `json:"children"`
|
||
}
|
||
|
||
//
|
||
// Reads Configs/HouseBuildConfig.json(4 行)+
|
||
// Configs/HouseFurnitureTemplateConfig.json(322 行),并把模板树按 buildId 索引好。
|
||
// <para>消费点只有一个:GameRouter.House.cs 的 AskLoadHouseData(63109556) ——
|
||
// 客户端进房子时会用 houseId 问服务端要 HouseBuildingClientData,
|
||
// 我们拿本目录把「房子本来该有的家具」塞进 FloorBuildInfoDict,
|
||
// 否则客户端拿到的是空表 ⇒ 毛坯房。</para>
|
||
// <para>⛑ 两张表都带 Lazy 缓存 ⇒ 改了要重启服务端
|
||
// (和 NpcCatalog.json 一个规矩)。</para>
|
||
//
|
||
var (
|
||
HouseFurnitureTemplateCatalog4229938_cacheLock sync.RWMutex
|
||
HouseFurnitureTemplateCatalog4229938_cached = false
|
||
HouseFurnitureTemplateCatalog4229938_entries []any
|
||
)
|
||
|
||
// LoadHouseFurnitureTemplateCatalog4229938 loads catalog records from client config directory
|
||
func LoadHouseFurnitureTemplateCatalog4229938(configDir string) ([]any, error) {
|
||
HouseFurnitureTemplateCatalog4229938_cacheLock.RLock()
|
||
if HouseFurnitureTemplateCatalog4229938_cached {
|
||
defer HouseFurnitureTemplateCatalog4229938_cacheLock.RUnlock()
|
||
return HouseFurnitureTemplateCatalog4229938_entries, nil
|
||
}
|
||
HouseFurnitureTemplateCatalog4229938_cacheLock.RUnlock()
|
||
|
||
HouseFurnitureTemplateCatalog4229938_cacheLock.Lock()
|
||
defer HouseFurnitureTemplateCatalog4229938_cacheLock.Unlock()
|
||
if HouseFurnitureTemplateCatalog4229938_cached { return HouseFurnitureTemplateCatalog4229938_entries, nil }
|
||
|
||
filePath := filepath.Join(configDir, "HouseFurnitureTemplateCatalog.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)
|
||
}
|
||
}
|
||
|
||
HouseFurnitureTemplateCatalog4229938_entries = result
|
||
HouseFurnitureTemplateCatalog4229938_cached = true
|
||
return result, nil
|
||
}
|
||
|
||
// HouseBuildConfig.Id → 定义。找不到就 false。
|
||
func HouseFurnitureTemplateCatalog4229938_TryGetBuild(buildId uint32, build HouseBuildDefinition4229938) bool {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_TryGetBuild
|
||
return false
|
||
}
|
||
|
||
//
|
||
// 这套房子的「顶层家具」节点列表 —— 已经剥掉了模板自己的根容器
|
||
// (模板根的 FurnitureId == 0,和线格式里的 IndoorBuildInfo.Root 是同一个东西,
|
||
// 所以它的**子节点**才是要挂到 Root.ChildrenDict 上的那一层)。
|
||
// <para>模板根万一是真家具(FurnitureId != 0)就把它自己当顶层,免得整棵树丢掉。</para>
|
||
//
|
||
func HouseFurnitureTemplateCatalog4229938_TopLevelNodes(buildId uint32) []HouseFurnitureTemplateNode4229938 {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_TopLevelNodes
|
||
return nil
|
||
}
|
||
|
||
//
|
||
// 按 buildId + 模板节点号找节点 —— 2026-10-01 为「家具机关」新增。
|
||
// <para>谁需要它:客户端 AskCreateHouseFurnitureGadgets 只给
|
||
// placedId(= houseId*100000 + nodeId,且线上是 32 位截断形态),
|
||
// 服务端要把它反解成「哪件家具、在哪」,唯一入口就是这张表。
|
||
// 详见 GameRouter.HouseFurnitureGadget.cs。</para>
|
||
// <para>索引按 buildId 懒建并缓存(TopLevelNodes 已剥掉模板根容器,
|
||
// 这里再从顶层递归收全部后代)。四套房各自的模板节点号互不重叠,但按 build 分开更稳。</para>
|
||
//
|
||
func HouseFurnitureTemplateCatalog4229938_TryGetNode(buildId uint32, nodeId uint32, node HouseFurnitureTemplateNode4229938) bool {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_TryGetNode
|
||
return false
|
||
}
|
||
|
||
func HouseFurnitureTemplateCatalog4229938_BuildIndex(buildId uint32) map[uint32]HouseFurnitureTemplateNode4229938 {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_BuildIndex
|
||
return nil
|
||
}
|
||
|
||
func HouseFurnitureTemplateCatalog4229938_Collect(index map[uint32]HouseFurnitureTemplateNode4229938, node HouseFurnitureTemplateNode4229938) {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_Collect
|
||
}
|
||
|
||
// 树里一共有多少个「真家具」节点(FurnitureId != 0),只用于日志 / 诊断。
|
||
func HouseFurnitureTemplateCatalog4229938_CountFurniture(nodes []HouseFurnitureTemplateNode4229938) int32 {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_CountFurniture
|
||
return 0
|
||
}
|
||
|
||
func HouseFurnitureTemplateCatalog4229938_LoadBuilds(path string, target map[uint32]HouseBuildDefinition4229938) *string {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_LoadBuilds
|
||
return nil
|
||
}
|
||
|
||
func HouseFurnitureTemplateCatalog4229938_LoadTemplates(path string, target map[uint32]HouseFurnitureTemplateNode4229938) *string {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_LoadTemplates
|
||
return nil
|
||
}
|
||
|
||
func HouseFurnitureTemplateCatalog4229938_U32(source any, name string) uint32 {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_U32
|
||
return 0
|
||
}
|
||
|
||
// 读 {"X":..,"Y":..,"Z":..} 这种嵌套对象里的一个 float。
|
||
func HouseFurnitureTemplateCatalog4229938_F32(source any, outer string, inner string) float32 {
|
||
// Catalog helper HouseFurnitureTemplateCatalog4229938_F32
|
||
return 0
|
||
}
|
||
|
||
type HouseFurnitureTemplateCatalog4229938_Snapshot struct {
|
||
Builds map[uint32]HouseBuildDefinition4229938 `json:"builds"`
|
||
Nodes map[uint32]HouseFurnitureTemplateNode4229938 `json:"nodes"`
|
||
Error *string `json:"error"`
|
||
}
|
||
|