package catalogs import ( "encoding/json" "os" "path/filepath" "sync" ) var _ = json.RawMessage{} var _ = sync.Mutex{} var _ = os.ReadFile var _ = filepath.Join // // 改装店(Smokey Drift / ApplyCar)的改装件映射目录:读 Configs/VehicleTuningCatalog.json。 // 为什么要有这个文件:上游 donor(repair-shop.zip)是在运行时直接啃官方原始表 // ConfigDump/{VehicleConfig,ShopCommodityConfig,ConsumableConfig,VehiclePartConfig, // VehiclePartSuitConfig}.json(合计 22 MB)。我们的服务端没有 ConfigDump 目录,所以把 // donor 那四个 loader 的结果预先投影成一个 93 KB 的 JSON。 // 四条链(与 donor 语义逐字一致,只是把运行时读表换成读投影): // // ShopCommodityConfig.Id → .BindId → ConsumableConfig[ICommonItemConfig.Id].BindId // (= 零件 id)→ 命中 VehiclePartConfig 记 (partId, PartTag, IsSuit=false); // 命中 VehiclePartSuitConfig 记 (partId, 18, IsSuit=true)。 // VehicleConfig.DefaultSuitId → VehiclePartSuitConfig 行 // (Suit[] / WheelModelA[] / WheelModelB[] / SuitPaint)。 // // 生成:ConfigDump.zip!ConfigDump_v3/*.json(build 4229938)。711 条改装店商品 // 全部能映射到零件(实测 711/711);套件行里的轮子与车漆在 VehiclePartConfig 里 // 零缺失(147 行全查过),所以展开出的 Parts 一定能过客户端的车轮检查。 // 文件缺失/损坏不致命:目录变空、LoadError 说明原因,购买链照旧 ack ok。 // 回滚:删掉这个 json 即可(或者不动它,因为它只被本文件读)。 // var ( VehicleTuningCatalog4229938_cacheLock sync.RWMutex VehicleTuningCatalog4229938_cached = false VehicleTuningCatalog4229938_entries []any ) // LoadVehicleTuningCatalog4229938 loads catalog records from client config directory func LoadVehicleTuningCatalog4229938(configDir string) ([]any, error) { VehicleTuningCatalog4229938_cacheLock.RLock() if VehicleTuningCatalog4229938_cached { defer VehicleTuningCatalog4229938_cacheLock.RUnlock() return VehicleTuningCatalog4229938_entries, nil } VehicleTuningCatalog4229938_cacheLock.RUnlock() VehicleTuningCatalog4229938_cacheLock.Lock() defer VehicleTuningCatalog4229938_cacheLock.Unlock() if VehicleTuningCatalog4229938_cached { return VehicleTuningCatalog4229938_entries, nil } filePath := filepath.Join(configDir, "VehicleTuningCatalog.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) } } VehicleTuningCatalog4229938_entries = result VehicleTuningCatalog4229938_cached = true return result, nil } func VehicleTuningCatalog4229938_TryGetCommodityPart(commodityId uint32, part TuningPart) bool { // Catalog helper VehicleTuningCatalog4229938_TryGetCommodityPart return false } func VehicleTuningCatalog4229938_TryGetDefaultSuit(vehicleConfigId uint32, suitId uint32) bool { // Catalog helper VehicleTuningCatalog4229938_TryGetDefaultSuit return false } func VehicleTuningCatalog4229938_TryGetSuitRow(suitId uint32, row SuitRow) bool { // Catalog helper VehicleTuningCatalog4229938_TryGetSuitRow return false } func VehicleTuningCatalog4229938_TryGetPartTag(partId uint32, tag uint32) bool { // Catalog helper VehicleTuningCatalog4229938_TryGetPartTag return false } func VehicleTuningCatalog4229938_Arr(e any, name string) []uint32 { // Catalog helper VehicleTuningCatalog4229938_Arr return nil } // 一个商品对应的改装件。IsSuit=true 时 PartId 是 VehiclePartSuitConfig 的行 id。 type TuningPart struct { PartId uint32 `json:"partId"` PartTag uint32 `json:"partTag"` IsSuit bool `json:"isSuit"` } // VehiclePartSuitConfig 一行:套件零件 + 前后两条轮轴 + 套件车漆。 type SuitRow struct { Suit []uint32 `json:"suit"` WheelModelA []uint32 `json:"wheelModelA"` WheelModelB []uint32 `json:"wheelModelB"` SuitPaint uint32 `json:"suitPaint"` } type VehicleTuningCatalog4229938_Snapshot struct { DefaultSuits map[uint32]uint32 `json:"defaultSuits"` CommodityParts map[uint32]TuningPart `json:"commodityParts"` PartTags map[uint32]uint32 `json:"partTags"` SuitRows map[uint32]SuitRow `json:"suitRows"` Error *string `json:"error"` }