92 lines
3.5 KiB
Go
92 lines
3.5 KiB
Go
package catalogs
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"sync"
|
||
|
|
)
|
||
|
|
|
||
|
|
var _ = json.RawMessage{}
|
||
|
|
var _ = sync.Mutex{}
|
||
|
|
var _ = os.ReadFile
|
||
|
|
var _ = filepath.Join
|
||
|
|
|
||
|
|
//
|
||
|
|
// Reads the carriage composition of every metro train out of the two rail config tables the
|
||
|
|
// client already ships: RailLineConfig.json (lineId -> TrainTemplateId) and
|
||
|
|
// RailTrainConfig.json (templateId -> CarriageIds).
|
||
|
|
// Why the server needs this at all — see GameRouter's OnAskMetroGadgetIds: the client
|
||
|
|
// builds each LightRail prefab itself (LightRail_4_405/carriage0|1|2/Seats/Gadgets_888_LightRailChair*)
|
||
|
|
// and then asks the server which gadget instance ids belong to that train. Verified 2026-09-23 by
|
||
|
|
// frida dump of a live train:
|
||
|
|
// carriage0 = 4 seats, carriage1 = 6 seats (the injected ids only stuck on carriage1 back when we
|
||
|
|
// answered one flat count for every carriage) — the client matches InnerGadgetIds index-for-index
|
||
|
|
// against the carriage's own seat slots, so the answer must be one entry per carriage, each with
|
||
|
|
// exactly that carriage's seat count.
|
||
|
|
// The mapping metroId -> line comes from the ids the client asks with: 103/104/105 are line 1 trains,
|
||
|
|
// 205/206/207 are line 2, 304 line 3, 400/405 line 4 — i.e. lineId = metroId / 100.
|
||
|
|
// Composition per line (build 4229938):
|
||
|
|
// line 1/2 (Bayshore, template 1 LightRailVehicle01) -> [10, 2, 2, 2, 3]
|
||
|
|
// line 3 (Central, template 2 LightRailVehicle01) -> [11, 7, 7, 7, 8]
|
||
|
|
// line 4 (East, template 3 LightRailVehicle03) -> [4, 5, 9] <- the one we dumped
|
||
|
|
// line 5-8 (test) template 4 LightRailVehicle01 -> [10]
|
||
|
|
// line 9-14 (1/2/3号线 上下行, template 5 CX01) -> [12, 13, 13, 13, 14]
|
||
|
|
// line 15 (画舫 TourBoat01, template 6) -> [15]
|
||
|
|
// Seat counts per carriage template are NOT in any config (they live in the prefab), so they are a
|
||
|
|
// knob on MetroGadgetSettings — seed it from the in-game dump.
|
||
|
|
//
|
||
|
|
var (
|
||
|
|
MetroCarriageCatalog4229938_cacheLock sync.RWMutex
|
||
|
|
MetroCarriageCatalog4229938_cached = false
|
||
|
|
MetroCarriageCatalog4229938_entries []any
|
||
|
|
)
|
||
|
|
|
||
|
|
// LoadMetroCarriageCatalog4229938 loads catalog records from client config directory
|
||
|
|
func LoadMetroCarriageCatalog4229938(configDir string) ([]any, error) {
|
||
|
|
MetroCarriageCatalog4229938_cacheLock.RLock()
|
||
|
|
if MetroCarriageCatalog4229938_cached {
|
||
|
|
defer MetroCarriageCatalog4229938_cacheLock.RUnlock()
|
||
|
|
return MetroCarriageCatalog4229938_entries, nil
|
||
|
|
}
|
||
|
|
MetroCarriageCatalog4229938_cacheLock.RUnlock()
|
||
|
|
|
||
|
|
MetroCarriageCatalog4229938_cacheLock.Lock()
|
||
|
|
defer MetroCarriageCatalog4229938_cacheLock.Unlock()
|
||
|
|
if MetroCarriageCatalog4229938_cached { return MetroCarriageCatalog4229938_entries, nil }
|
||
|
|
|
||
|
|
filePath := filepath.Join(configDir, "MetroCarriageCatalog.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)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
MetroCarriageCatalog4229938_entries = result
|
||
|
|
MetroCarriageCatalog4229938_cached = true
|
||
|
|
return result, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
//
|
||
|
|
// Carriage template ids of one train, in carriage order (index 0 = the client's carriage0).
|
||
|
|
// False when the metroId does not resolve to a known line/template.
|
||
|
|
//
|
||
|
|
func MetroCarriageCatalog4229938_TryGetCarriageTemplates(metroId int32, carriageTemplates []int32) bool {
|
||
|
|
// Catalog helper MetroCarriageCatalog4229938_TryGetCarriageTemplates
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|