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/gameserver/routers/game_router_functional_npc.go

122 lines
5.9 KiB
Go
Raw Permalink 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 routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// Fifth entity channel: functional NPCs at fixed city spots (shop clerks, ticket sellers, ...).
// Same four-step announce sequence as the citizen channels — this file does not invent a spawn
// path, it only supplies different coordinates. Instead of "a plot's pavement spots, how many
// decided by the hour" the positions are固定的: one per venue, already snapped onto pavement by
// the generator, so a shop clerk ends up where the shop actually is.
// What the NPC *does* is not our problem here: F-key behaviour (open a shop panel, buy a ticket,
// start a mahjong match) is driven entirely by the client's own lua through
// AgentConfig.InteractSetting. The server just has to put a body there. That is deliberate — it
// is the whole reason this card is cheap.
// Two ways in, sharing one placement helper so they can never disagree:
// • the follow loop (EnsureFunctionalNpcs) — how they normally appear: walk up to
// a shop and its clerk is standing there;
// • the panel button (SpawnFunctionalNpcsAsync) — "put them all down now".
//
func GameRouter_FunctionalNpc_FunctionalNpcStateOf(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_FunctionalNpc_FunctionalNpcStateOf
var zero any; return zero
}
// World-ready hook: start the follow loop. Idempotent; no-op when disabled.
func GameRouter_FunctionalNpc_EnsureFunctionalNpcs(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_FunctionalNpc_EnsureFunctionalNpcs
var zero any; return zero
}
// Disconnect / scene switch: stop the loop. The client clears the entities itself.
func GameRouter_FunctionalNpc_StopFunctionalNpcs(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_FunctionalNpc_StopFunctionalNpcs
var zero any; return zero
}
// How many the follow loop currently has standing. Panel display only.
func GameRouter_FunctionalNpc_FunctionalNpcActiveCount(ctx context.Context, session *GameSession) int32 {
// Router implementation for GameRouter_FunctionalNpc_FunctionalNpcActiveCount
return 0
}
func GameRouter_FunctionalNpc_RunFunctionalNpcLoopAsync(ctx context.Context, session *GameSession, owner any, token context.Context) any {
// Router implementation for GameRouter_FunctionalNpc_RunFunctionalNpcLoopAsync
var zero any; return zero
}
func GameRouter_FunctionalNpc_TickFunctionalNpcsAsync(ctx context.Context, session *GameSession, owner any, cfg any) any {
// Router implementation for GameRouter_FunctionalNpc_TickFunctionalNpcsAsync
var zero any; return zero
}
func GameRouter_FunctionalNpc_RemoveFunctionalNpcAsync(ctx context.Context, session *GameSession, state any, owner any, id uint64, spot any) any {
// Router implementation for GameRouter_FunctionalNpc_RemoveFunctionalNpcAsync
var zero any; return zero
}
//
// ★★★ R93(2026-09-27)—— **落脚高度吸附**:把点位声明的 Y 换成「该 XZ 上真实地面/物件的高度」。
// 为什么必须做:FunctionalNpcSpots.json 的 Y 是用 CivilianDistricts 人行道点
// 反向找的(见该文件 note)。那套人行道点只在**主城平地**有数据,一旦点位的 XZ 落在
// **高台/庙会/室内**,找出来的就是别处(常常是 y≈0/2 那一层)的 Y。
// 实测标本(2026-09-27):Tea Shop Owner(40954014)/Tea Stall Owner(40954022) 声明 Y=2.00,
// 而同 XZ 上 2528 件场景物一律 **y≈166~172** ⇒ NPC 被生成在**地下 167 m**,
// 现象 = 用户所说的「摊位的npc呢」(看着像根本没刷,其实刷了、埋了)。
// 数据源 = config/scene_item_placements.json(mtime 热重载,4877 件带真实 y)。
// 取点位 XZ **半径 内最近的若干件**的 y 中位数当落脚高度:
// 中位数对「同一点位旁边既有台面又有地面」的情况比最近邻稳。
// 命中不到(荒地/新点位)⇒ **原样返回**,绝不猜。
//
func GameRouter_FunctionalNpc_SnapGroundY(ctx context.Context, x float32, y float32, z float32, samples int32, snapped float32, radius float32) float32 {
// Router implementation for GameRouter_FunctionalNpc_SnapGroundY
return 0
}
//
// One placement: announce + remember. Returns the entity id, or 0 when the spot's ids are not
// in the catalogs (a bad row in the json must not kill the batch).
//
func GameRouter_FunctionalNpc_PlaceFunctionalNpcAsync(ctx context.Context, session *GameSession, state any, owner any, spot any) uint64 {
// Router implementation for GameRouter_FunctionalNpc_PlaceFunctionalNpcAsync
return 0
}
//
// Panel button: place every functional NPC of the current scene (nearest first when a radius
// is given, radius <= 0 = the whole scene). Anything already standing is skipped.
//
func GameRouter_FunctionalNpc_SpawnFunctionalNpcsAsync(ctx context.Context, session *GameSession, radius float32, includeSemantic bool) any {
// Router implementation for GameRouter_FunctionalNpc_SpawnFunctionalNpcsAsync
var zero any; return zero
}
func GameRouter_FunctionalNpc_Distance2(ctx context.Context, spot any, x float32, z float32) float32 {
// Router implementation for GameRouter_FunctionalNpc_Distance2
return 0
}
type FunctionalNpcSessionState struct {
SyncRoot any `json:"syncRoot"`
Cts *context.CancelFunc `json:"cts"`
Loop *any `json:"loop"`
// entityId -> the spot it was placed for. Doubles as the "already placed" set.
Active map[uint64]FunctionalNpcSpot4229938 `json:"active"`
//
// Formwork ids whose placement has been started but not finished yet.
// ⛑ Placement awaits several network writes and happens OUTSIDE the lock, so a tick that
// starts while the previous batch is still in flight cannot see it in Active
// and would place the same clerk again — two identical NPCs stacked on one spot.
//
Pending []uint32 `json:"pending"`
// Scene the Active entries belong to; a change wipes them.
Raid uint32 `json:"raid"`
}