This repository has been archived on 2026-10-31. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Ananta-ps/internal/catalogs/functional_npc_spot_catalog4229938.go

128 lines
4.6 KiB
Go

package catalogs
import (
"encoding/json"
"os"
"path/filepath"
"sync"
)
var _ = json.RawMessage{}
var _ = sync.Mutex{}
var _ = os.ReadFile
var _ = filepath.Join
//
// One functional NPC placed at a fixed spot: a shop clerk, a ticket seller, a mahjong host...
// Read from Configs/FunctionalNpcSpots.json — see _build_spots.py.
//
//
// Where the data comes from (three hops, none of which lives in the NPC table itself):
// 1. AgentDataSetsInteractSettingConfig says what the F key does for an AgentConfig id
// (OpenNpcShop(94100024), BuyBoatTicket(), ShowDialog(...));
// 2. ShopConfig.Position / IndoorMapFunctionPointConfig.Coordinate / IndoorConfig
// give the venue's world position — that is the anchor;
// 3. the anchor XZ is snapped onto the nearest CivilianDistricts pavement spot so the NPC
// stands on a walkable surface at a real ground height instead of on a roof or in mid-air.
// The server's only job is to announce the entity. Everything the F key does afterwards is client
// lua — the server neither validates nor pays for a purchase.
//
type FunctionalNpcSpot4229938 struct {
NpcFormworkId uint32 `json:"npcFormworkId"`
Name string `json:"name"`
PoiActionId uint32 `json:"poiActionId"`
X float32 `json:"x"`
Y float32 `json:"y"`
Z float32 `json:"z"`
Facing float32 `json:"facing"`
Function string `json:"function"`
Raid uint32 `json:"raid"`
Anchor string `json:"anchor"`
Actions []string `json:"actions"`
Labels []string `json:"labels"`
Note string `json:"note"`
}
//
// Reads Configs/FunctionalNpcSpots.json. Small file (36 spots), parsed once behind a Lazy.
// A missing or malformed file is not fatal: the catalog goes empty and
// LoadError explains why, so the panel can say so instead of throwing on load.
//
var (
FunctionalNpcSpotCatalog4229938_cacheLock sync.RWMutex
FunctionalNpcSpotCatalog4229938_cached = false
FunctionalNpcSpotCatalog4229938_entries []any
)
// LoadFunctionalNpcSpotCatalog4229938 loads catalog records from client config directory
func LoadFunctionalNpcSpotCatalog4229938(configDir string) ([]any, error) {
FunctionalNpcSpotCatalog4229938_cacheLock.RLock()
if FunctionalNpcSpotCatalog4229938_cached {
defer FunctionalNpcSpotCatalog4229938_cacheLock.RUnlock()
return FunctionalNpcSpotCatalog4229938_entries, nil
}
FunctionalNpcSpotCatalog4229938_cacheLock.RUnlock()
FunctionalNpcSpotCatalog4229938_cacheLock.Lock()
defer FunctionalNpcSpotCatalog4229938_cacheLock.Unlock()
if FunctionalNpcSpotCatalog4229938_cached { return FunctionalNpcSpotCatalog4229938_entries, nil }
filePath := filepath.Join(configDir, "FunctionalNpcSpotCatalog.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)
}
}
FunctionalNpcSpotCatalog4229938_entries = result
FunctionalNpcSpotCatalog4229938_cached = true
return result, nil
}
//
// 规则 199:这个模板能不能当"人"铺出去。
// ⛑ 判据是 DonorNpcCatalogEntry4229938.AgentPersonaId == 0 —— 物件和敌人都是 0,真人都非 0。
// 模型段位(8695xxxx…)不能当判据:869xxxxx 段里混着 621 个真人(BVB-阿姆斯 / Yun Feng / Tie Shan)。
// 案由:铺出来的「NPC」按 F 显示「厄反广播」,实际是 40120273「大喇叭音箱(完成后)」—— 一个音箱。
// ⚠️ fail-open:查不到 NpcCatalog 时放行,别因为这道保险把整张点位表清空。
//
func FunctionalNpcSpotCatalog4229938_IsPlaceablePerson(npcFormworkId uint32) bool {
// Catalog helper FunctionalNpcSpotCatalog4229938_IsPlaceablePerson
return false
}
// Every spot belonging to <raidId>; an unknown raid falls back to none.
func FunctionalNpcSpotCatalog4229938_ForRaid(raidId uint32, includeSemantic bool) []FunctionalNpcSpot4229938 {
// Catalog helper FunctionalNpcSpotCatalog4229938_ForRaid
return nil
}
//
// Spots of <raidId> inside <radius> metres of (x, z), nearest first. radius <= 0
// means "every spot of that raid", which is what you want for a 36-item list anyway.
//
func FunctionalNpcSpotCatalog4229938_WithinRadius(raidId uint32, x float32, z float32, radius float32, includeSemantic bool) []FunctionalNpcSpot4229938 {
// Catalog helper FunctionalNpcSpotCatalog4229938_WithinRadius
return nil
}
func FunctionalNpcSpotCatalog4229938_Strings(source any, name string) []string {
// Catalog helper FunctionalNpcSpotCatalog4229938_Strings
return nil
}