136 lines
4.7 KiB
Go
136 lines
4.7 KiB
Go
package catalogs
|
||
|
||
import (
|
||
"encoding/json"
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
)
|
||
|
||
var _ = json.RawMessage{}
|
||
var _ = sync.Mutex{}
|
||
var _ = os.ReadFile
|
||
var _ = filepath.Join
|
||
|
||
//
|
||
// 龙栖村的一个互动摊位机关:打气球 / 套圈 / 刮刮乐 / 五子棋 / 打年糕 …。
|
||
// 读自 Configs/MiniGameStalls.json。
|
||
//
|
||
//
|
||
// ★ 为什么需要它(2026-09-27,第 89 轮):
|
||
// 这批摊位机关**不在**客户端会自己实例化的清单里。它们的真身有两半:
|
||
// ① 客户端 Spoon 图里有一个 GADGET 节点(StartBalloonNode / StartRingTossNode …)
|
||
// ② 关卡块里有一份官方世界摆位
|
||
// 和 GymEquipment / PartyCamp 完全同因:grid-AOI 下发**不驱动** LX6.Item.GadgetBlob,
|
||
// 所以客户端一件都不会自己出现 ⇒ 必须服务端拿 pathId + 官方坐标显式摆一次。
|
||
// ★ pathId 空间是「服务端 catalog」那一套(Configs/GadgetCatalog.json,2935 条),
|
||
// ⛔ 不是客户端 GadgetConfig.json 的 1367 条(那是另一套 id,
|
||
// 例:同一件 Gadget_DaQiQiu 在那边是 79304020,在服务端 catalog 是 912387408)。
|
||
// 服务端下发的 pathId 必须取**能被服务端 catalog 查到名字**的那个,否则
|
||
// BuildGadgetEntityInfo 会 Warn「not in GadgetCatalog.json」并原样发出。
|
||
// ★ 官方世界坐标逐条解自关卡块(工具 gym_tools/_r87_minigame_gadget.py,
|
||
// 结果 _r87_minigame_gadget.txt;记录结构 = 命中点 - 28 是记录头,
|
||
// +0/+4/+8 = f32 x/y/z,+16 = yaw,+28 = pathId)。
|
||
//
|
||
type MiniGameStallItem4229938 struct {
|
||
PathId int32 `json:"pathId"`
|
||
Name string `json:"name"`
|
||
X float32 `json:"x"`
|
||
Y float32 `json:"y"`
|
||
Z float32 `json:"z"`
|
||
Yaw float32 `json:"yaw"`
|
||
UniqueId uint64 `json:"uniqueId"`
|
||
}
|
||
|
||
// 一个摊位片区:一个锚点、一个触发半径,和半径内的摊位机关。
|
||
type MiniGameStallSpot4229938 struct {
|
||
Name string `json:"name"`
|
||
Raid uint32 `json:"raid"`
|
||
X float32 `json:"x"`
|
||
Z float32 `json:"z"`
|
||
Radius float32 `json:"radius"`
|
||
Items []MiniGameStallItem4229938 `json:"items"`
|
||
}
|
||
|
||
//
|
||
// Reads Configs/MiniGameStalls.json. Tiny file, parsed once behind a Lazy.
|
||
// A missing or malformed file is not fatal: the catalog goes empty and
|
||
// LoadError explains why, so the caller can log it instead of throwing.
|
||
//
|
||
var (
|
||
MiniGameStallCatalog4229938_cacheLock sync.RWMutex
|
||
MiniGameStallCatalog4229938_cached = false
|
||
MiniGameStallCatalog4229938_entries []any
|
||
)
|
||
|
||
// LoadMiniGameStallCatalog4229938 loads catalog records from client config directory
|
||
func LoadMiniGameStallCatalog4229938(configDir string) ([]any, error) {
|
||
MiniGameStallCatalog4229938_cacheLock.RLock()
|
||
if MiniGameStallCatalog4229938_cached {
|
||
defer MiniGameStallCatalog4229938_cacheLock.RUnlock()
|
||
return MiniGameStallCatalog4229938_entries, nil
|
||
}
|
||
MiniGameStallCatalog4229938_cacheLock.RUnlock()
|
||
|
||
MiniGameStallCatalog4229938_cacheLock.Lock()
|
||
defer MiniGameStallCatalog4229938_cacheLock.Unlock()
|
||
if MiniGameStallCatalog4229938_cached { return MiniGameStallCatalog4229938_entries, nil }
|
||
|
||
filePath := filepath.Join(configDir, "MiniGameStallCatalog.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)
|
||
}
|
||
}
|
||
|
||
MiniGameStallCatalog4229938_entries = result
|
||
MiniGameStallCatalog4229938_cached = true
|
||
return result, nil
|
||
}
|
||
|
||
// Spots whose anchor is within <radius> metres of (x, z), nearest first.
|
||
func MiniGameStallCatalog4229938_WithinRadius(x float32, z float32, radius float32) []MiniGameStallSpot4229938 {
|
||
// Catalog helper MiniGameStallCatalog4229938_WithinRadius
|
||
return nil
|
||
}
|
||
|
||
func MiniGameStallCatalog4229938_Dist2(spot MiniGameStallSpot4229938, x float32, z float32) float32 {
|
||
// Catalog helper MiniGameStallCatalog4229938_Dist2
|
||
return 0
|
||
}
|
||
|
||
//
|
||
// u64 that the capture script emits as a JSON string (no double round-trip). System.Text.Json
|
||
// throws InvalidOperationException ("requires an element of type 'Number'") if you call
|
||
// TryGetUInt64 on a string element, so accept both shapes — one bad uid must not kill the file.
|
||
//
|
||
func MiniGameStallCatalog4229938_U64(source any, name string) uint64 {
|
||
// Catalog helper MiniGameStallCatalog4229938_U64
|
||
return 0
|
||
}
|
||
|
||
func MiniGameStallCatalog4229938_Str(source any, name string) string {
|
||
// Catalog helper MiniGameStallCatalog4229938_Str
|
||
return ""
|
||
}
|
||
|
||
func MiniGameStallCatalog4229938_Floats(source any, name string, take int32) []float32 {
|
||
// Catalog helper MiniGameStallCatalog4229938_Floats
|
||
return nil
|
||
}
|
||
|