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/indoor_room_catalog4229938.go
T

178 lines
6.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package catalogs
import (
"encoding/json"
"os"
"path/filepath"
"sync"
)
var _ = json.RawMessage{}
var _ = sync.Mutex{}
var _ = os.ReadFile
var _ = filepath.Join
//
// 一条室内房间(IndoorConfig)。占地取自 MiniMapPos[0..3]。
//
// IndoorConfig.Id。
// 英文名(如 Spiko Hotel)。
// 中文/策划名(如 亚兰游戏分红)。
// 所属副本 —— 用来把「别的副本的室内」排除掉(见 §护栏)。
// ★ 官方字段:这间室内能不能从外面看见。
// MapFloorList(楼层列表;不是 y 范围,见类注释的警告)。
// Coordinate(多数条目为空数组)。
type IndoorRoomEntry4229938 struct {
Id int32 `json:"id"`
Name string `json:"name"`
NameTag string `json:"nameTag"`
ParentRaid uint32 `json:"parentRaid"`
SceneId uint32 `json:"sceneId"`
VisibleOutside bool `json:"visibleOutside"`
MinX float32 `json:"minX"`
MinZ float32 `json:"minZ"`
MaxX float32 `json:"maxX"`
MaxZ float32 `json:"maxZ"`
Floors []int32 `json:"floors"`
Coordinate []float32 `json:"coordinate"`
Width float32 `json:"width"`
Depth float32 `json:"depth"`
Area float32 `json:"area"`
}
//
// ★★★ 第 50 轮(2026-09-26):室内层判定。读 Configs/IndoorConfig.json。
// <para>为什么需要它。舞会的官方锚点
// PartySpot(2574.24, 80.135, 1271) 与舞池点 DanceSpot(2605.33, 80, 1269.74)
// 横向都落在 IndoorConfig#150 "Spiko Hotel"(NameTag="亚兰游戏分红")的占地里,
// 而那间室内的官方字段 VisibleOutside = false —— 从外面看不见。
// 我们却把 10 个 NPC 当露天物摆在 y ≈ 80,于是现场就是「角色全悬在空中」
// (用户 04:56 / 04:58 两张实拍)。</para>
// <para>为什么不能靠 cell/sector 解决。
// 机关网格(SyncGadgetGridAOIDecrease)是按 40 m cell + SectorIdList 推的,
// 而 GadgetCells.json 里 根本没有舞池那两个 cell
// ((64,31) / (65,31))⇒ 回落 [0] = 室外 ⇒ 客户端把室内层的道具
// 当室外物造了出来。所以必须走「占地 + VisibleOutside」这条独立判据。</para>
// <para>占地怎么来的。MiniMapPos 是小地图显示矩形
// [minX, minZ, maxX, maxZ, …4 个精灵像素值]。
// 实测校准(2026-09-26):Spiko Hotel 的 x[2515,2610] z[1162,1285]
// 同时含 PartySpot 与 DanceSpot;另外 5 个样本(1UP / Sonic Boom / 保龄球馆 / Dreamy Bay /
// 绿岛宴会厅)的 Coordinate 有 4 个精确落在矩形内、2 个只差 &lt; 10 m
// ⇒ 它是粗占地(整数、可能外扩几米),不是碰撞体边界。够用来做可见性过滤。</para>
// <para>⚠ 已知局限(别把它当通用高度表)。
// <list type="bullet">
// <item>y 一律不参与判定。MapFloorList 的语义自相矛盾 ——
// Spiko Hotel 写 [-5,-4,-3,-2,-1,1],而三处官方来源(PartyConfig
// /PartyDanceSpotConfig/客户端烘焙表)都写 y ≈ 80。这个矛盾未定案
// ⇒ 本类只做 x/z 占地,不猜 y。</item>
// <item>770 条里只有 143 条有可用矩形,且这 143 条全部 VisibleOutside=false
// ⇒ 无法用「可见的室内」反证判据(本类不依赖这一点)。</item>
// <item>干净拆成三档 ParentRaid:23300888 ×111 / 23300999 ×20 / 23301277 ×12
// —— 最后那档里有 8 条 2000×2000 m 的占位矩形(*_raid1277),
// 所以查表时必须给 raidId,再加单边上限双保险。</item>
// </list></para>
// <para>护栏(只影响「命中率」,不影响「命中后的语义」):
// ① ParentRaid 必须等于调用方给的 raidId(0 视为通配);
// ② 矩形单边 &gt; MaxSideMeters 视为脏数据并跳过(本副本最大是 773 m 的 Tunnel)。
// 两条都会记进 SkippedCount,可用 Rooms 复查。</para>
//
const (
// 单边上限:超过就当地图占位脏数据丢掉(官方表里有 2000×2000 的)。
IndoorRoomCatalog4229938_MaxSideMeters float32 = 1000
)
var (
IndoorRoomCatalog4229938_cacheLock sync.RWMutex
IndoorRoomCatalog4229938_cached = false
IndoorRoomCatalog4229938_entries []any
)
// LoadIndoorRoomCatalog4229938 loads catalog records from client config directory
func LoadIndoorRoomCatalog4229938(configDir string) ([]any, error) {
IndoorRoomCatalog4229938_cacheLock.RLock()
if IndoorRoomCatalog4229938_cached {
defer IndoorRoomCatalog4229938_cacheLock.RUnlock()
return IndoorRoomCatalog4229938_entries, nil
}
IndoorRoomCatalog4229938_cacheLock.RUnlock()
IndoorRoomCatalog4229938_cacheLock.Lock()
defer IndoorRoomCatalog4229938_cacheLock.Unlock()
if IndoorRoomCatalog4229938_cached { return IndoorRoomCatalog4229938_entries, nil }
filePath := filepath.Join(configDir, "IndoorRoomCatalog.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)
}
}
IndoorRoomCatalog4229938_entries = result
IndoorRoomCatalog4229938_cached = true
return result, nil
}
//
// 找包含 , 的房间;同一处常有多条记录叠着 ⇒
// 取面积最小的那条(最具体)。
//
func IndoorRoomCatalog4229938_TryFindAt(x float32, z float32, raidId uint32, room IndoorRoomEntry4229938) bool {
// Catalog helper IndoorRoomCatalog4229938_TryFindAt
return false
}
//
// 找包含 , 的、从外面看不见的房间
// (VisibleOutside == false)。命中 = 这个点按露天刷是不对的。
//
func IndoorRoomCatalog4229938_TryFindHiddenAt(x float32, z float32, raidId uint32, room IndoorRoomEntry4229938) bool {
// Catalog helper IndoorRoomCatalog4229938_TryFindHiddenAt
return false
}
func IndoorRoomCatalog4229938_Str(row any, name string) string {
// Catalog helper IndoorRoomCatalog4229938_Str
return ""
}
func IndoorRoomCatalog4229938_U32(row any, name string) uint32 {
// Catalog helper IndoorRoomCatalog4229938_U32
return 0
}
func IndoorRoomCatalog4229938_Bool(row any, name string) bool {
// Catalog helper IndoorRoomCatalog4229938_Bool
return false
}
// 读一个数值:JSON 里同一字段既有整数(2515)也有小数(80.135),两种都要吃。
func IndoorRoomCatalog4229938_Num(el any) *float32 {
// Catalog helper IndoorRoomCatalog4229938_Num
return nil
}
func IndoorRoomCatalog4229938_ReadIntArray(row any, name string) []int32 {
// Catalog helper IndoorRoomCatalog4229938_ReadIntArray
return nil
}
func IndoorRoomCatalog4229938_ReadFloatArray(row any, name string) []float32 {
// Catalog helper IndoorRoomCatalog4229938_ReadFloatArray
return nil
}