94 lines
4.2 KiB
Go
94 lines
4.2 KiB
Go
package routers
|
||
|
||
import (
|
||
"context"
|
||
"sync"
|
||
)
|
||
|
||
var _ = sync.Mutex{}
|
||
var _ = context.Background
|
||
|
||
//
|
||
// 街上正常行走的行人(AetherCity crowd)。
|
||
// ★ 这条线是**客户端自驱**的:AetherPedManager 用 ContextSteering + ZoneGraph Wander 自己走,
|
||
// 服务端**没有任何移动包可发**(MethodId 表里没有 AskUpdateMoveDatas 这类 RPC)。
|
||
// 服务端只负责三件事:
|
||
// ① SyncAetherAIInitDatas 打开 HasZoneGraph —— 已有 EnsureAetherVehicleInit() 负责
|
||
// ② SyncSetCrowdDensity(68996045) —— 解锁客户端 ECS 人群生成器
|
||
// ③ SyncCrowdSpecifiedDensityRefresh(68195167) —— 在玩家周围的盒子里按密度补人
|
||
// 玩家走远(默认 35m)后重发 ③,否则走出盒子就没人了。
|
||
// 契约权威 = dump.cs `IGameSceneToClient` 接口签名,见 CrowdMethods4229938.cs 文件头。
|
||
//
|
||
//
|
||
// 关掉人群时的「清零」推送:把全局密度压到 0,并在玩家脚下补一个同样为 0 的刷新盒。
|
||
// ⛑️ 为什么不是「什么都不发」:客户端的 AetherCity 人群是**自驱**的 —— HasZoneGraph 一打开
|
||
// (SyncAetherAIInitDatas)它就按场景自带数据自己生成人,我们的 SyncSetCrowdDensity 只是
|
||
// override。所以「不发密度包」= 回到客户端默认密度 = 街上照样有人。要没人只能主动压 0。
|
||
// ⛑️ 不要发 RevertToNormal=true —— 那是「恢复默认密度」,效果正好相反。
|
||
//
|
||
func GameRouter_Crowd_PushCrowdDisabledAsync(ctx context.Context, session *GameSession, pos Vec3, reason string) bool {
|
||
// Router implementation for GameRouter_Crowd_PushCrowdDisabledAsync
|
||
return true
|
||
}
|
||
|
||
func GameRouter_Crowd_ShouldPushCrowd(ctx context.Context, density float32) bool {
|
||
// Router implementation for GameRouter_Crowd_ShouldPushCrowd
|
||
return true
|
||
}
|
||
|
||
func GameRouter_Crowd_CrowdCfg(ctx context.Context, ) any {
|
||
// Router implementation for GameRouter_Crowd_CrowdCfg
|
||
var zero any; return zero
|
||
}
|
||
|
||
func GameRouter_Crowd_CrowdAnchor(ctx context.Context, state any) Vec3 {
|
||
// Router implementation for GameRouter_Crowd_CrowdAnchor
|
||
var zero Vec3; return zero
|
||
}
|
||
|
||
//
|
||
// T0-8:把玩家脚下的地块类型与该地块的时段人流曲线合成实际密度。
|
||
// density = 全局 CrowdDensity × 地块类型系数 × max(HourlyFlow[hour], CrowdHourFloor)
|
||
// 为什么不用 UrbanDiversityConfig 的 PopulationDensity / DegreeOfBusyness:
|
||
// 实测 681 个地块里这两个字段几乎恒为 0(只有沙滩区有值),没有信息量。
|
||
// LandPlotType + HourlyFlow 是仅有的两个可用维度,HourlyFlow 已按各自峰值归一化到 1.0。
|
||
//
|
||
func GameRouter_Crowd_ResolveCrowdDensity(ctx context.Context, state any, pos Vec3) any {
|
||
// Router implementation for GameRouter_Crowd_ResolveCrowdDensity
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// 世界进入(OnLoadingFinished)时激活客户端原生人群。
|
||
// 必须在 EnsureAetherVehicleInit 之后 —— 没有 HasZoneGraph=true 客户端根本不建人群层。
|
||
//
|
||
func GameRouter_Crowd_PublishAmbientCrowdAsync(ctx context.Context, rpcCtx *RpcContext) any {
|
||
// Router implementation for GameRouter_Crowd_PublishAmbientCrowdAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
//
|
||
// 玩家移动时流式补人:离开上次中心超过阈值就重发一次密度刷新盒。
|
||
// 由 GameRouter.Movement.cs 的位移报告处 fire-and-forget 调用。
|
||
//
|
||
func GameRouter_Crowd_CheckAndRefreshCrowdOnPlayerMoveAsync(ctx context.Context, session *GameSession, currentPos Vec3) any {
|
||
// Router implementation for GameRouter_Crowd_CheckAndRefreshCrowdOnPlayerMoveAsync
|
||
var zero any; return zero
|
||
}
|
||
|
||
// 面板 / GM 显式刷新。返回是否真的发了(被合并掉返回 false)。
|
||
func GameRouter_Crowd_RefreshAmbientCrowdAsync(ctx context.Context, session *GameSession, overrideDensity any) bool {
|
||
// Router implementation for GameRouter_Crowd_RefreshAmbientCrowdAsync
|
||
return true
|
||
}
|
||
|
||
//
|
||
// 只算不推:给 GM 面板回报「玩家脚下现在会算出什么密度」。
|
||
// 面板改完参数不动也能看到这个值变化,不用真的走 35 米才知道。
|
||
//
|
||
func GameRouter_Crowd_ProbeCrowdDensity(ctx context.Context, session *GameSession) any {
|
||
// Router implementation for GameRouter_Crowd_ProbeCrowdDensity
|
||
var zero any; return zero
|
||
}
|
||
|