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

127 lines
5.6 KiB
Go

package routers
import (
"context"
"sync"
)
var _ = sync.Mutex{}
var _ = context.Background
//
// Playable characters standing in the city, each at whatever their own daily schedule says they
// are doing right now — Richie on the treadmill, Garm at the claw machine, and so on.
// Two reasons this file exists:
// 1. Official has them roaming from the start (the 趴卜 schedule tab and the big-map markers exist
// precisely so the player can go find them). We only ever materialised one at the moment the
// player switched <em>away</em> from that character, so walking to a schedule coordinate found
// nobody — which is exactly what the player reported on 09-25.
// 2. The client unloads distant units and never re-adds them by itself: coming back to a spot from
// far away shows an empty pavement until you switch the character away and back. So the server
// has to own the distance bookkeeping — place on enter, retire on exit, place again on return.
// That is not a new idea; it is the same follow-loop + hysteresis shape as
// GameRouter.EnsureFunctionalNpcs, only with different coordinates.
// Coordinates and the activity id come straight from the client's own tables
// (see NpcActivityCatalog4229938): nothing here is invented.
//
func GameRouter_RosterNpc_RosterNpcStateOf(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_RosterNpc_RosterNpcStateOf
var zero any; return zero
}
// World-ready hook: start the follow loop. Idempotent; no-op when disabled.
func GameRouter_RosterNpc_EnsureRosterNpcs(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_RosterNpc_EnsureRosterNpcs
var zero any; return zero
}
// Disconnect / scene switch: stop the loop. The client clears the entities itself.
func GameRouter_RosterNpc_StopRosterNpcs(ctx context.Context, session *GameSession) any {
// Router implementation for GameRouter_RosterNpc_StopRosterNpcs
var zero any; return zero
}
// How many are currently standing. Panel display only.
func GameRouter_RosterNpc_RosterNpcActiveCount(ctx context.Context, session *GameSession) int32 {
// Router implementation for GameRouter_RosterNpc_RosterNpcActiveCount
return 0
}
//
// ★ 切人接管时**立即**撤掉常驻摆在日程点上的那具身体(09-26 00:4x 加)。
// ⛑⛑ 为什么必须同步做:开了 SwitchToScheduleSpot 之后,玩家会直接瞬移到
// 角色的日程点位。而那个点位上常驻化很可能已经摆了一具同样的身体
// (他本来就「在城里过日子」)⇒ 瞬移过去就是「两个里希重叠」的老毛病(规则 166)。
// 常驻循环 1.5 秒才跳一次,等它自己撤(spirit == activeSpirit)中间那一秒玩家
// 就盯着两个自己 —— 所以切人时主动撤一次。
// ⛑ 撤不掉也不至于更糟:RemoveRosterNpcAsync 已经是 Leave+Aether 双发(规则 166)。
//
func GameRouter_RosterNpc_RetireRosterNpcForSwitchAsync(ctx context.Context, session *GameSession, spiritId uint32) bool {
// Router implementation for GameRouter_RosterNpc_RetireRosterNpcForSwitchAsync
return true
}
//
// spiritId -&gt; unitId for everything currently on the field. The GM panel uses it to mark
// which rows are actually standing in the world right now (as opposed to merely scheduled).
//
func GameRouter_RosterNpc_RosterNpcPlacements(ctx context.Context, session *GameSession) map[string]any {
// Router implementation for GameRouter_RosterNpc_RosterNpcPlacements
return nil
}
func GameRouter_RosterNpc_RunRosterNpcLoopAsync(ctx context.Context, session *GameSession, owner any, token context.Context) any {
// Router implementation for GameRouter_RosterNpc_RunRosterNpcLoopAsync
var zero any; return zero
}
func GameRouter_RosterNpc_TickRosterNpcsAsync(ctx context.Context, session *GameSession, owner any, cfg any) any {
// Router implementation for GameRouter_RosterNpc_TickRosterNpcsAsync
var zero any; return zero
}
func GameRouter_RosterNpc_PlaceRosterNpcAsync(ctx context.Context, session *GameSession, state any, owner any, spiritId uint32, choice any, cfg any, mode string) any {
// Router implementation for GameRouter_RosterNpc_PlaceRosterNpcAsync
var zero any; return zero
}
func GameRouter_RosterNpc_RemoveRosterNpcAsync(ctx context.Context, session *GameSession, state any, owner any, spiritId uint32) any {
// Router implementation for GameRouter_RosterNpc_RemoveRosterNpcAsync
var zero any; return zero
}
func GameRouter_RosterNpc_Dist2(ctx context.Context, x float32, z float32, px float32, pz float32) float32 {
// Router implementation for GameRouter_RosterNpc_Dist2
return 0
}
//
// 目标点位 米内(3D)是否已经站着别的 NPC。
// 用 3D 是为了让「同一栋楼 1 楼和 2 楼各站一个」这种正常情况不误判 —— 只有真的贴在一起才算冲突。
//
func GameRouter_RosterNpc_Taken(ctx context.Context, x float32, y float32, z float32, poses []any, separation float32) bool {
// Router implementation for GameRouter_RosterNpc_Taken
return true
}
type RosterNpcSessionState struct {
SyncRoot any `json:"syncRoot"`
Cts *context.CancelFunc `json:"cts"`
Loop *any `json:"loop"`
// spiritId -&gt; what was placed for it. Doubles as the "already placed" set.
Active map[uint32]RosterNpcPlacement `json:"active"`
// Scene the Active entries belong to; a change wipes them.
Raid uint32 `json:"raid"`
// 是否已经打过一次「名册里有多少人没有可落地活动」的诊断行(只打一次,别刷屏)。
Diagnosed bool `json:"diagnosed"`
}
type RosterNpcPlacement struct {
UnitId uint64 `json:"unitId"`
X float32 `json:"x"`
Y float32 `json:"y"`
Z float32 `json:"z"`
ActivityId uint32 `json:"activityId"`
}