package catalogs import ( "encoding/json" "os" "path/filepath" "sync" ) var _ = json.RawMessage{} var _ = sync.Mutex{} var _ = os.ReadFile var _ = filepath.Join // // One purchasable house, read from Configs/HouseConfig.json(官方表,**只有 5 条**)。 // 为什么服务端需要它:客户端买房的链路是 // BuyHouseUtils.BuyTheHouse(houseId) → // AskNpcShopCommodityInfo(houseCfg.ShopId) → // AskBuyCommodity(houseCfg.ShopId, houseCfg.Commodity, 1)。 // 服务端收到的只有 shopId + commodityId,要反查回 houseId 必须靠这张表 // —— 没有任何别的 RPC 会告诉服务端"玩家买的是哪套房"。 // 字段来源(`E:\ConfigDump\ConfigDump_v3\HouseConfig.json` 逐字抄,2026-09-30 核对): // // Id 11200000 / 11200003 / 11200004 / 11200005 / 11200006 // ShopId 94100080「新启房产」(5 条共用) // Commodity 94206003 / 94206000 / 94206001 / 94206002 / 94206004 // MapEntrance 212 / 215 / 216 / 217 / 218 ← MapentranceConfig.Type = 12 (House) // Raid 0(11200000)/ 23300888(其余 4 条,= Nova 开放世界) // GarageIndoorId 201 / 301 / 300 / 299 / 379 ← IndoorConfig,ParentRaid 23300888 // ⛔ 11200003 这条是官方错数据:写成了 301(绿屿公馆主体),真实车库是 302 // (IndoorConfig 301 绿屿公馆 / 302 绿屿公馆车库)。另外 4 条都等于各自车库。 // 客户端已用 fastpatch(tools/garage_indoor_fix.lua)改回 302;本表不改, // 保持与官方 dump 一致,需要判断车库室内请用 GameRouter.Door.GarageIndoorIds。 // BuildId 0 / 2 / 3 / 4 / 5 ← HouseBuildConfig.Id,★ 家具链的入口 // // ⛔ Raid = 0 的 11200000「岸北悠居公寓」是唯一的 IsBuild = false 条目 // —— 它是普通公寓(不可自建),其余 4 套 IsBuild = true(可装修)。 // 别因为 Raid 是 0 就当成坏数据丢掉。 // // HouseConfig.Id,也是客户端 Lua 里的 houseId。 // HouseConfig.Commodity,购买时客户端上报的那个商品号。 // 房产商店(94100080)。 // MapentranceConfig.Id,大地图上那个房产入口。 // 房子所在 raid。0 = 未归属具体 raid(岸北悠居公寓)。 // IndoorConfig.Id,自家车库的室内体积。 // // HouseBuildConfig.Id —— 2026-09-30 为「自带家具」补的字段。 // 0 = 这套房没有可装修体(岸北悠居公寓),拿它查 // HouseFurnitureTemplateCatalog4229938 只会拿到空家具。 // type HouseDefinition4229938 struct { Id uint32 `json:"id"` Name string `json:"name"` Quality uint32 `json:"quality"` ShopId uint32 `json:"shopId"` Commodity uint32 `json:"commodity"` MapEntrance uint32 `json:"mapEntrance"` Raid uint32 `json:"raid"` IsBuild bool `json:"isBuild"` GarageIndoorId uint32 `json:"garageIndoorId"` Location string `json:"location"` BuildId uint32 `json:"buildId"` // // HouseConfig.ParkingSpaceCount —— 这套房车库有几个车位(岸北悠居 2 / 绿屿 8 / // 旧物仓 2 / 观澜 8 / 素光 2)。车库「找空位」和校验车位号用。2026-09-30 为车库功能补。 // ParkingSpaceCount uint32 `json:"parkingSpaceCount"` // // HouseConfig.VisitorExit = [x, y, z, facing] —— 访客离开这套房时的落点, // 绝对坐标(不是 Spoon 航点 id)。2026-09-30 为「驶离车库」补。 // 为什么用它:车库出库事务里客户端自己算的落点是 // HouseConfig.GarageOutWaypoint(Spoon 航点 id,服务端没有 Spoon 位置表), // 而且 ExitTimeline 只有 1 个元素时(素光小筑)客户端连 Spoon 反查都不做, // afterPosition 直接留全零 ⇒ 过场结束会被甩到世界原点。 // VisitorExit 是 HouseConfig 里唯一现成的绝对坐标落点,实测同层且就在房门外 // (素光 = (1104.8, 8.53, 2391.8),车库内玩家在 (1094.5, 8.5, 2368.2))。 // VisitorExit HousePoint4229938 `json:"visitorExit"` } // // HouseConfig 里 [x, y, z, facing] 形状的坐标列(VisitorEntrance / // VisitorExit)。Facing 单位是度。 // type HousePoint4229938 struct { X float32 `json:"x"` Y float32 `json:"y"` Z float32 `json:"z"` Facing float32 `json:"facing"` IsUsable bool `json:"isUsable"` } // // Reads Configs/HouseConfig.json. 5 rows, all purchasable from shop 94100080. // 消费点只有两处:① AskBuyCommodity 里按 commodityId 反查 houseId; // ② 诊断日志 / 管理面板。 // var ( HouseCatalog4229938_cacheLock sync.RWMutex HouseCatalog4229938_cached = false HouseCatalog4229938_entries []any ) // LoadHouseCatalog4229938 loads catalog records from client config directory func LoadHouseCatalog4229938(configDir string) ([]any, error) { HouseCatalog4229938_cacheLock.RLock() if HouseCatalog4229938_cached { defer HouseCatalog4229938_cacheLock.RUnlock() return HouseCatalog4229938_entries, nil } HouseCatalog4229938_cacheLock.RUnlock() HouseCatalog4229938_cacheLock.Lock() defer HouseCatalog4229938_cacheLock.Unlock() if HouseCatalog4229938_cached { return HouseCatalog4229938_entries, nil } filePath := filepath.Join(configDir, "HouseCatalog.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) } } HouseCatalog4229938_entries = result HouseCatalog4229938_cached = true return result, nil } func HouseCatalog4229938_TryGet(houseId uint32, house HouseDefinition4229938) bool { // Catalog helper HouseCatalog4229938_TryGet return false } // 商品号 → 房产。购买链路的唯一入口:客户端只上报 commodityId。 func HouseCatalog4229938_TryGetByCommodity(commodityId uint32, house HouseDefinition4229938) bool { // Catalog helper HouseCatalog4229938_TryGetByCommodity return false } // 这个 shopId 是不是房产商店(94100080)。 func HouseCatalog4229938_IsHouseShop(shopId uint32) bool { // Catalog helper HouseCatalog4229938_IsHouseShop return false } func HouseCatalog4229938_LoadPair() any { // Catalog helper HouseCatalog4229938_LoadPair var zero any; return zero } func HouseCatalog4229938_TryRead(node any, house *HouseDefinition4229938) bool { // Catalog helper HouseCatalog4229938_TryRead return false } // 读 [x, y, z, facing] 形状的坐标列;缺列 / 形状不对都退化成全零。 func HouseCatalog4229938_Point(source any, name string) HousePoint4229938 { // Catalog helper HouseCatalog4229938_Point var zero HousePoint4229938; return zero } func HouseCatalog4229938_U32(source any, name string) uint32 { // Catalog helper HouseCatalog4229938_U32 return 0 } func HouseCatalog4229938_Bool(source any, name string) bool { // Catalog helper HouseCatalog4229938_Bool return false } func HouseCatalog4229938_Str(source any, name string) string { // Catalog helper HouseCatalog4229938_Str return "" }