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/pkg/protocol/methods/crowd_methods4229938.go
T

93 lines
5.4 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 methods
//
// AetherCity 人群(crowd / 行人)S2C 契约,build 4229938。
// ⛑️ 字段与顺序的唯一权威 = `dump.cs` 里 `IGameSceneToClient` 接口的 abstract 签名
// (`Assembly-CSharp-ULTIMATE/ux_rpc/ux_game_all.dump.cs`)。本文件逐条对齐,不要按
// RPCSerializeAuto.lua 改(那份对这批包不可信 —— 见硬规则 34)。
// 关键设计:客户端 AetherCity 的人群是**客户端自驱**的(AetherPedManager 用
// ContextSteering + ZoneGraph Wander 自己走)。服务端要做的只有两件事:
// ① SyncAetherAIInitDatas 打开 HasZoneGraph(已有 EnsureAetherVehicleInit 负责)
// ② SyncSetCrowdDensity + SyncCrowdSpecifiedDensityRefresh 告诉客户端"在玩家周围生成多少人"
// 服务端**不发任何移动包**(没有 AskUpdateMoveDatas 这类 RPC)。
//
//
// IGameSceneToClient.SyncSetCrowdDensity(bool revertToNormal, float overrideDensity) = 68996045。
// 打开客户端 ECS 人群生成器(覆盖全局密度)。
//
//
// IGameSceneToClient.SyncCrowdSpecifiedDensityRefresh(UXVector3 position, UXVector3 extends,
// float densityFactor) = 68195167。
// 在 position 周围 extends 这个盒子里按 densityFactor 生成/补齐行人。玩家走远了要重发。
//
//
// UX.Game.ClientCrowdInitData : ClientBaseEntityData(TypeDefIndex 32676)。
// 单个行人的出生数据。字段顺序 = 本类 7 个字段在前,继承的 ClientBaseEntityData
// 4 个字段(Id / Position / Facing / EulerAngles)在**最后** —— 与客户端派生字段列表一致。
// ⛑️ NpcFormworkId 是 **AgentConfig** 的 id(4013xxxx),不是 AgentPersonaConfig(452xxxxx)。
// 填错客户端打 `创建AgentUnit失败!AgentConfigId为0!` 并丢掉这个人。
//
//
// IGameSceneToClient.SyncAetherAICrowdAdd(ClientCrowdInitData crowd) = 68757757。
// 手动投放一个行人给客户端的 Aether AI。单 class 参数 ⇒ 内部类走 Complex(0xFF 标记)。
//
//
// IGameSceneToClient.AskAetherNpcUpdatePathForObstacle(67228857) —— C→S,**行人自己撞墙求助**。
// 三个字段:`ulong entityId + UXVector3 障碍点 + float radius`(donor v2 的 `CrowdMethods.cs`,
// 他们整场只收到 1 次,但那一次 = 那个人**站着 12.8 秒**)。
// ⛑️ 字段顺序照 donor 的契约抄;当前只用于打日志观察,解析错了也不会影响别的包。
//
//
// IGameSceneToClient.AskClientNpcFindPath(67974714) —— C→S INVOKE,客户端为它手下的单位问路。
// 请求体 = ulong id + UXVector3 from + UXVector3 to(28 字节;长度不符客户端会拒收)。
//
//
// AskClientNpcFindPath 的应答 FindPathResult。
// ⛑️ 字段与顺序真源 = `RPCDeserializeAuto.lua`:`midToReturnMessageReader[67974714]`
// → `Base.ReadStruct(reader, Auto.Reader[688])`;`Auto.Reader[688]` =
// `Points:list7<UXVector3>` + `Flags:list7<byte>`。
// 与兜底字节 `FF 01 FF 01`(两个空 list7)完全吻合。
// 顶层是 struct(**无 marker**);list7 计数带 +1 偏置,空集合 = `FF 01`。
//
//
// IGameSceneToClient.SyncAetherAINpcRemove(ulong pid) = 68332284。
// ⛑️ dump 权威签名是**单个 ulong**,不是 List<ulong>。
// (donor_lyco082 那份写成 List 是猜的,别抄。)pid = 当初 ClientCrowdInitData.Id。
//
//
// IGameSceneToClient.SyncCrowdSurroundZone(int spoonId, UXVector3 center, float radius, bool add,
// float removeRadius) = 68024180。把圆形区域登记成客户端自己人群的聚集区(add=true)。
//
//
// IGameSceneToClient.SyncCrowdClearZone(int spoonId, UXVector3 center, float radius, bool add,
// float removeRadius, CrowdClearZoneType zoneType) = 68910103。禁人区。
//
//
// SyncAgentForceGo(ulong id, bool isForceGo) = 68698324。
// 已生成但站着不动的 agent 用它启动行为树。
//
//
// UX.Game.MoveWanderingData : BattleMoveDataBase(TypeDefIndex 32747)= 68745518 的参数。
// ⛑️ 字段顺序照抄 donor1 `WorldMethods.cs`(它实机验证过,49 字节):
// **本类 8 个字段在前,扁平化的基类字段在后** —— 与 dump 的内存布局一致。
// 不要重排、不要删字段。
//
//
// IGameSceneToClient.SyncMoveWandering(MoveWanderingData data) = 68745518。
// ★★ 让一个已投放的 NPC/行人"自己走起来"的唯一官方包。
// 它**不带目的地**——只有半径、角度窗口和时间预算,路径由客户端 ZoneGraph/AetherAI 自己挑。
// ⇒ 服务端根本不需要路网来做"行走",只需要周期续期(MaxTime 是总时长,走完就永久站住)。
//
//
// SyncChangeNpcMoveDesiredSpeed(entityId u64, desiredSpeed f32) = 68739456。
// ⛑️ `ClientStaticNpcInitData` **没有 DesiredSpeed 字段**,速度只能靠这个包单独下发;
// 不发 ⇒ 客户端 `AgentEntitySyncHandler.GetDesiredSpeed` 拿 0 ⇒ 即使有目的地也不动。
//
//
// Client -> server AskAgentPoiActionDone(67016793):12 字节,u64 agentId + u32 poiActionId,
// poiActionId 就是 UrbanDiversityPOIActionConfig 的 Id。
// 移植自捐赠端 DremkaPS(2026-09-24,其 GameScene/CrowdMethods.cs)。他们的注释写得很直接:
// 没有这个 handler,agent 会保持在动作播完那一刻的姿势 —— 「动作演完就定格」这个症状。
// ⛑ 客户端是**成串**上报的(350 ms 内 31 条、间隔约 10 ms),所以任何应答都要做过流闸门。
//