MassBattle Docsv1.19.20

UMassBattleNetworkSubsystem

UCLASS WorldSubsystem

Source/MassBattle/Public/Subsystems/MassBattleNetworkSubsystem.h

概述 Overview

锁步网络架构的核心中枢(UCLASS(Config = MassBattle, DefaultConfig))。集中承载六条主线:① 指令队列——EnqueueNetCommand/DequeueNetCommandsForTick 的确定性排序、去重与迟到判罚,由 UMassBattleSubsystem::Tick 的锁步命令执行循环驱动;② lockstep 自动分流数据块——大命令经 TCP 块传输 + 引用命令的暂存/汇聚/超时清理(ReceivedLockstepDataBlocks / UploadedLockstepDataBlocks / PendingBlockCommands),外加客户端"块未到/宿主未复制"的暂存等待与本地时间线冻结(StagedBlockCommands / StagedSpawnCommands);③ per-tick 哈希与快照——注册表驱动的 EntityHash 折叠、周期性快照缓存、本地/服务器双路径 resync 恢复(ApplyEntitySnapshotPayload 全类别实体重建);④ 客户端调速——UpdateNetworkClientPacing 按 tick 偏移输出速度比率并驱动追帧/暂停;⑤ 快照模板注册表——RegisterNetworkTemplateData 幂等注册,Key 统一 DA 路径或自动命名;⑥ LockstepNetID 宿主注册表——spawn/despawn 指令双端定位组件。另含 TCP 快照传输生命周期与 BP 事件委托(OnTickCompleted/OnNetCommandExecuted/OnNetworkEvent)。所有路径都服务于同一纪律:双端确定性一致。

The central hub of the lockstep network architecture (UCLASS(Config = MassBattle, DefaultConfig)). It hosts six main lines: ① command queue — deterministic ordering, dedup and late-command penalty in EnqueueNetCommand/DequeueNetCommandsForTick, driven by the lockstep command-execution loop in UMassBattleSubsystem::Tick; ② lockstep auto-flood data blocks — large commands travel as TCP blocks plus a reference command, with staging/convergence/timeout pruning (ReceivedLockstepDataBlocks / UploadedLockstepDataBlocks / PendingBlockCommands), plus the client-side block-not-arrived / host-not-replicated stage-and-wait with local-timeline freeze (StagedBlockCommands / StagedSpawnCommands); ③ per-tick hash and snapshot — registry-driven EntityHash folding, periodic snapshot caching, and dual-path (local/server) resync recovery with ApplyEntitySnapshotPayload rebuilding every entity category; ④ client pacing — UpdateNetworkClientPacing derives a tick-speed ratio from the tick delta and drives fast-forward/pause; ⑤ snapshot template registry — idempotent RegisterNetworkTemplateData keyed by DA path or auto-generated name; ⑥ LockstepNetID host registry — lets spawn/despawn commands locate bound components on both peers. It also owns the TCP snapshot transport lifecycle and BP event delegates (OnTickCompleted/OnNetCommandExecuted/OnNetworkEvent). Every path serves one discipline: identical determinism on both peers.

继承 Inheritance

UWorldSubsystem → UMassBattleNetworkSubsystem

枚举 Enums

EMassBattleNetworkEventType UENUM(BlueprintType), enum class : uint8

统一网络事件类型——失步、暂停、追帧通知的归类,携带在 FMassBattleNetworkEventData 中经 OnNetworkEvent 广播。下列"发射点"均经 grep 验证。

Unified network event types — categorizes desync, pause and fast-forward notifications carried in FMassBattleNetworkEventData and broadcast via OnNetworkEvent. The emit sites below are all grep-verified.

值 Values
值 Value说明 Description
PauseForServerSnapshot为等待服务端快照而暂停(默认值)。发射点:EnterDesyncRecovery / TriggerServerResync / 调速冷却分支。Pause to wait for a server snapshot (the default). Emitted by EnterDesyncRecovery / TriggerServerResync / the pacing cooldown branch.
PauseForServerToCatchUp暂停以等待服务器追上。发射点:UMassBattleSubsystem::Tick 的服务器追赶分支。Pause while the server catches up. Emitted by the server-catch-up branch in UMassBattleSubsystem::Tick.
PauseLocalSim暂停本地模拟(客户端)。发射点:UMassBattleSubsystem::BroadcastGamePauseEvent。Pause the local sim (client). Emitted by UMassBattleSubsystem::BroadcastGamePauseEvent.
PauseServerSim暂停服务器模拟。发射点:UMassBattleSubsystem::BroadcastGamePauseEvent。Pause the server sim. Emitted by UMassBattleSubsystem::BroadcastGamePauseEvent.
ResumeAfterServerCatchUp服务器追上后恢复。发射点:UMassBattleSubsystem::Tick 的恢复分支。Resume after the server caught up. Emitted by the resume branch in UMassBattleSubsystem::Tick.
ResumeLocalSim恢复本地模拟。发射点:UMassBattleSubsystem::BroadcastGamePauseEvent。Resume the local sim. Emitted by UMassBattleSubsystem::BroadcastGamePauseEvent.
ResumeServerSim恢复服务器模拟。发射点:UMassBattleSubsystem::BroadcastGamePauseEvent。Resume the server sim. Emitted by UMassBattleSubsystem::BroadcastGamePauseEvent.
FastForwardViaLocalSnapshot经本地快照追帧(bLastRecoveryWasLocal 为真)。发射点:BeginFastForward。Fast-forward via a local snapshot (when bLastRecoveryWasLocal is true). Emitted by BeginFastForward.
FastForwardViaServerSnapshot经服务端快照追帧。发射点:BeginFastForward。Fast-forward via a server snapshot. Emitted by BeginFastForward.
FastForwardCatchUp无快照的纯追帧(一般落后,不经过恢复)。发射点:BeginFastForward。Pure catch-up fast-forward without a snapshot (moderate lag, no recovery). Emitted by BeginFastForward.
FastForwardCompleted追帧完成。发射点:UMassBattleSubsystem::Tick 的 FF 完成块。Fast-forward completed. Emitted by the FF-completion block in UMassBattleSubsystem::Tick.
ClientKickedPacingTimeout客户端因调速超时被踢。发射点:AMassBattleNetworkGameModeBase(PlayerIndex 携带被踢客户端)。Client kicked for pacing timeout. Emitted by AMassBattleNetworkGameModeBase (PlayerIndex carries the kicked client).
CommandRejectedByWhitelist客户端命令被白名单闸门拒绝(1.19.20 新增值)。发射点:AMassBattleNetworkGameModeBase::ReceivePlayerCommand 的客户端命令闸门(默认拒绝:服务器权威 tag 一律拒绝,其余须显式列入 allow 集;TickCount 与 PlayerIndex 携带拒绝上下文)。Client command rejected by the whitelist gate (value added in 1.19.20). Emitted by the client-command gate in AMassBattleNetworkGameModeBase::ReceivePlayerCommand (default-deny: server-authority tags are always denied, everything else must be explicitly allow-listed; TickCount and PlayerIndex carry the rejection context).
ESnapshotFieldPolicy enum class : uint8 (嵌套)

快照字段策略——决定每个 UPROPERTY 字段在 blob 中的序列化/恢复方式。由 GetSnapshotFieldPolicy 静态分发函数产生,MB_ADD_FLD_POLICY 宏消费:UnsupportedTransient 与 RuntimeObjectLocalOnly 被排除出 blob(零大小、无布局条目)。

Snapshot field policy — decides how each UPROPERTY field serializes into / restores from the blob. Produced by the static dispatcher GetSnapshotFieldPolicy, consumed by the MB_ADD_FLD_POLICY macro: UnsupportedTransient and RuntimeObjectLocalOnly are excluded from the blob (zero size, no layout entry).

值 Values
值 Value说明 Description
DirectValue标量/无 string/name/array 的结构体,原字节 memcpy。默认策略。Scalar or struct without string/name/array members — raw memcpy. The default.
EntityHandleByUniqueIDFEntityHandle/FMassEntityHandle — 序列化目标 UniqueID,恢复时经 UID 映射解析(无效 → -1)。FEntityHandle/FMassEntityHandle — serialized as target UniqueID, resolved via the UID map on restore (invalid → -1).
DirectArrayRaw普通数组(内层非对象/句柄/强化目标条目)——元素原字节。Plain array (inner is not object/handle/reinforce entry) — raw element bytes.
EntityHandleArrayByUniqueIDFEntityArray(包装 TArray<FEntityHandle>)或 FEntityHandle 数组 — 逐元素 UID 序列化。FEntityArray (wraps TArray<FEntityHandle>) or arrays of FEntityHandle — per-element UID serialization.
ReinforceTargetEntryArrayByUniqueIDFReinforceTargetEntry 数组 — 目标句柄按 UID,附带 CachedLocation/ReportCount。Array of FReinforceTargetEntry — target handle by UID plus CachedLocation/ReportCount.
DirectStringFString — 长度前缀 + TCHAR 序列。FString — length prefix + TCHAR sequence.
DirectNameFName — 经字符串中转(索引不跨进程)。FName — round-trips via string (indices are process-local).
TemplateReference已声明未使用——当前 GetSnapshotFieldPolicy 不产生该策略(预留)。Declared but unused — the current GetSnapshotFieldPolicy never produces it (reserved).
SoftPath软对象引用 — 路径字符串,恢复时 ImportText 进 FSoftObjectPtr(不自动加载)。Soft object reference — path string; restore uses ImportText into FSoftObjectPtr (no auto-load).
RuntimeObjectByPath硬对象引用(FObjectPropertyBase 系,含类引用)— 路径序列化,恢复时 TryLoad 并注册 GC 根。Hard object reference (FObjectPropertyBase family incl. class refs) — path serialized; restore calls TryLoad and registers a GC root.
SoftPathArray软对象引用数组 — 逐元素路径字符串。Array of soft object references — per-element path strings.
RuntimeObjectByPathArray硬对象引用数组 — 逐元素路径 + TryLoad。Array of hard object references — per-element path + TryLoad.
QueryStructFMassBattleQuery/FEntityQuery — UPROPERTY 配置数组逐元素序列化;私有 lazy 缓存不同步,恢复端 MarkCacheDirty 重建。FMassBattleQuery/FEntityQuery — UPROPERTY config arrays serialized element-wise; private lazy caches not synced; restore calls MarkCacheDirty.
RuntimeObjectLocalOnly已声明;与 UnsupportedTransient 一样被布局宏排除出 blob。Declared; like UnsupportedTransient, excluded from the blob by the layout macro.
RuntimeObjectRebuild已声明未使用——当前策略函数不产生该策略(预留)。Declared but unused — the current policy function never produces it (reserved).
UnsupportedTransient瞬态/不支持 — 以 _Previous 结尾的变更检测缓存字段;排除出 blob。Transient/unsupported — fields whose names end with _Previous (change-detection caches); excluded from the blob.
EHashFieldCategory enum class : uint8 (嵌套,纯 C++,无 UHT)

哈希字段分类——镜像快照布局服务于 per-entity EntityHash 折叠。由 GetHashFieldPolicy 从快照策略映射:EntityHandleByUniqueID → EntityHandleToUID;DirectValue → 无 float 叶标量 RawBytes / 含 float 叶结构 CanonicalizeFloatStruct(按名识别 RandomStream → RandomStreamSeed);其余(数组/字符串/对象)→ Unsupported,构建期排除。

Hash field category — mirrors the snapshot layout for the per-entity EntityHash fold. Mapped from snapshot policies by GetHashFieldPolicy: EntityHandleByUniqueID → EntityHandleToUID; DirectValue → RawBytes for scalars without float leaves / CanonicalizeFloatStruct for structs with float leaves (name-detected RandomStream → RandomStreamSeed); everything else (arrays/strings/objects) → Unsupported, excluded at build time.

值 Values
值 Value说明 Description
RawBytes无 float 叶的标量/结构 — 哈希原始字节。Scalar/struct with no float leaves — hash raw bytes.
CanonicalizeFloatStruct含 float/double 叶的结构 — 先 -0.0→0.0 规范化再哈希(FloatLeaves 预计算叶偏移)。Struct with float/double leaves — canonicalize -0.0→0.0 then hash (FloatLeaves precompute leaf offsets).
RandomStreamSeedFRandomStream — 哈希 GetCurrentSeed()(int32→uint32 位级一致),而非原始结构。FRandomStream — hash GetCurrentSeed() (int32→uint32 bit-exact), not the raw struct.
EntityHandleToUIDFEntityHandle — 哈希目标 UniqueID(无效 → -1),与快照 blob 序列化器一致。FEntityHandle — hash the target UniqueID (invalid → -1), matching the snapshot blob serializer.
Unsupported字符串/数组/对象 — 构建期排除,不进入布局。String/array/object — excluded at build time, never enters a layout.

结构体 Structs

FMassBattleNetworkEventData USTRUCT(BlueprintType)

网络事件载荷——经 OnNetworkEvent(BlueprintAssignable)派发给 BP。

Network event payload — dispatched to BP via OnNetworkEvent (BlueprintAssignable).

成员变量 Members
名称 Name类型 Type默认值说明 Description
EventTypeEMassBattleNetworkEventTypePauseForServerSnapshot事件类型,见枚举表。Event type, see the enum table.
TickCountint320事件发生时的本地模拟 tick。Local simulation tick at the time of the event.
TargetTickint320追帧目标 tick(仅 FF 事件填充)。Fast-forward target tick (FF events only).
FFTicksint320追帧跨度(源码未在发射点填充,声明预留)。Fast-forward span (not filled by any emit site in the source; reserved).
bHashMatchedboolfalse哈希是否匹配(源码未在发射点填充,声明预留)。Whether the hash matched (not filled by any emit site in the source; reserved).
PlayerIndexint32-1受影响客户端的 PlayerId(仅踢出事件)。PlayerId of the affected client (kick events only).
FEntityNetworkEntry

逐实体网络条目——每 tick 由 MassBattleNetworkProcessor 收集,用于哈希折叠与缓存重建。

Per-entity network entry collected each tick by MassBattleNetworkProcessor for hash folding and cache rebuilds.

成员变量 Members
名称 Name类型 Type默认值说明 Description
UniqueIDint32-1实体全局 UID。Global entity UID.
EntityHashint640该实体本 tick 的折叠哈希。This entity's folded hash for the tick.
EntityHandleFEntityHandle—实体句柄。Entity handle.
CategoryEEMainTypeAgent类别盐 — 参与折叠并排序;全局 UID 计数器下属防御性(若未来回退 per-type 计数器则成为必需)。Category salt — folds with the hash and orders the fold; defensive under the global UID counter (would become required if per-type counters ever return).
FPerEntityHashTick

逐 tick 的逐实体 hash 快照(环形历史 PerEntityHashHistory 的元素)——用于定位 FF 后最先失步的实体。

Per-tick snapshot of per-entity hashes (element of the ring history PerEntityHashHistory) — used to identify the first entity that diverges after fast-forward.

成员变量 Members
名称 Name类型 Type默认值说明 Description
Tickint320所属模拟 tick。Owning simulation tick.
EntriesTArray<FEntityNetworkEntry>—该 tick 全部实体的哈希条目。Hash entries of all entities for this tick.
DiagComponentsTArray<FDiagAgentComp> (嵌套结构)—[DIAG] 该 tick 的逐 agent 分量哈希——失步检测时转储以定位分歧字段。嵌套 FDiagAgentComp 携带逐 fragment 分量哈希(HScale/HLoc/HRot/HMove/HTrace/HDet)加多组本案临时的裸拆分列(速度/目标/怀疑度/flags/倾斜/平均速度/光照/碰撞位、行为状态机与路径身份检查点、Goal 写点编号等,注释标注"随案清除")。[DIAG] per-agent component hashes at this tick — dumped at desync detection to isolate the diverging fragment. The nested FDiagAgentComp carries per-fragment component hashes (HScale/HLoc/HRot/HMove/HTrace/HDet) plus several hunt-temporary raw-split columns (velocity/goal/suspicion/flags/tilt/avg-speed/light/collider bits, behavior-state and path-identity checkpoints, the Goal writer id, etc. — comments mark them "remove with this hunt").
DiagProjectilesTArray<FDiagProjectileComp> (嵌套结构)—[DIAG] 该 tick 的逐 projectile 分量哈希——嵌套 FDiagProjectileComp 携带 HParams/HParamsRT/HLoc/HRot/HScale/HDet/HVar 分量、FProjectileParamsRT 的冷却/池倒计时拆分(HCoolDown/HPool)、IgnoreEntities 数量(不入 hash,仅诊断)与若干原始值。[DIAG] per-projectile component hashes at this tick — the nested FDiagProjectileComp carries HParams/HParamsRT/HLoc/HRot/HScale/HDet/HVar components, the FProjectileParamsRT cooldown/pool-countdown split (HCoolDown/HPool), the IgnoreEntities count (not hashed — diagnostic only) and several raw values.
FValidatedSnapshot

哈希已验证的快照——环形缓冲 ValidatedSnapshots 的元素,供本地失步恢复(TryLocalSnapshotRecovery)选择。

Hash-validated snapshot — element of the ring buffer ValidatedSnapshots, used by local desync recovery (TryLocalSnapshotRecovery).

成员变量 Members
名称 Name类型 Type默认值说明 Description
TickCountint320快照所属 tick。Tick the snapshot belongs to.
LocalHashint640捕获端本 tick 哈希。Capturing peer's hash for the tick.
ServerHashint640服务器哈希;0 = 尚未验证,验证通过后盖章。Server hash; 0 = not yet validated; stamped once validated.
PayloadTSharedPtr<FEntitySnapshotPayload, ESPMode::ThreadSafe>—快照载荷——共享 CachedLatestSnapshot 的同一对象(指针共享,零拷贝:旧的逐槽深拷贝是 17.5 万次 blob 分配,即客户端上 ValidatedRingStore 的全部成本);两个持有者只整体换指针、从不原地改,消费端变更前均已拷贝。Snapshot payload — shares the same object as CachedLatestSnapshot (pointer sharing, zero copy: the old per-slot deep copy was 175k blob allocations, the entire ValidatedRingStore cost on clients); both holders only ever swap the pointer and never mutate in place; all consumers copy before mutating.
FReceivedLockstepDataBlock

重组完成的大 lockstep 负载块——缓存至其引用命令触发(自动分流)。

Reassembled large lockstep-payload block cached until its reference command fires (auto-flood).

成员变量 Members
名称 Name类型 Type默认值说明 Description
DecompressedDataTArray<uint8>—解压后的负载字节。Decompressed payload bytes.
ExecuteTickint320引用命令的执行 tick。Execute tick of the reference command.
ReceiveTimedouble0.0到达墙钟(秒),供 30 秒宽限清理。Arrival wall-clock (seconds), for the 30s-grace pruning.
FPendingBlockCommand

暂存的上行引用命令(服务器)——等待其 TCP 块到达。块到达触发汇聚,过期条目被清理(High-1 竞态修复)。

Staged uplink reference command (server) waiting for its TCP block. Block arrival triggers convergence; stale entries are pruned (High-1 race fix).

成员变量 Members
名称 Name类型 Type默认值说明 Description
CmdFMassBattleNetCommand—等待块的引用命令。The reference command awaiting its block.
ReceiveTimedouble0.0暂存墙钟(秒),供超时清理。Staging wall-clock (seconds), for timeout pruning.
FSnapshotPropertyLayout

快照布局中的单个字段布局(blob 偏移、大小、策略)。

Per-field layout inside a snapshot layout (blob offset, size, policy).

成员变量 Members
名称 Name类型 Type默认值说明 Description
PropertyFProperty*nullptr反射字段句柄。Reflected field handle.
BlobOffsetint320字段在 blob 中的字节偏移(布局构建累加)。Byte offset of the field inside the blob (accumulated at layout build).
Sizeint320字段字节大小。Field byte size.
PolicyESnapshotFieldPolicyDirectValue序列化/恢复策略。Serialization/restore policy.
FSnapshotFragmentLayout

单个 fragment 的完整快照布局——属性列表 + blob 总大小。

Full snapshot layout of one fragment — property list + total blob size.

成员变量 Members
名称 Name类型 Type默认值说明 Description
ScriptStructUScriptStruct*nullptrfragment 的反射结构类型。Reflected struct type of the fragment.
PropertiesTArray<FSnapshotPropertyLayout>—参与 blob 的字段列表(瞬态/不支持策略被排除)。Fields participating in the blob (transient/unsupported policies excluded).
TotalBlobSizeint320blob 总字节数;0 表示无有效布局。Total blob bytes; 0 means no valid layout.
FHashFieldLayout

哈希布局中的单个字段布局(分类、大小、float 叶)。

Per-field layout inside a hash layout (category, size, float leaves).

成员变量 Members
名称 Name类型 Type默认值说明 Description
PropertyFProperty*nullptr反射字段句柄。Reflected field handle.
CategoryEHashFieldCategoryRawBytes哈希分类。Hash category.
Sizeint320字段字节大小。Field byte size.
StructUScriptStruct*nullptr仅 CanonicalizeFloatStruct 时设置。Set only for CanonicalizeFloatStruct.
FloatLeavesTArray<FHashFloatLeaf>—预计算的 float/double 叶偏移。Precomputed float/double leaf offsets.
FHashFragmentLayout

单个 fragment 的哈希布局——结构类型 + 字段列表。

Hash layout of one fragment — struct type + field list.

成员变量 Members
名称 Name类型 Type默认值说明 Description
ScriptStructUScriptStruct*nullptrfragment 的反射结构类型。Reflected struct type of the fragment.
FieldsTArray<FHashFieldLayout>—参与折叠的字段列表(Unsupported 排除)。Fields participating in the fold (Unsupported excluded).

公开方法 Public Methods

生命周期 Lifecycle

Initialize virtual void

USubsystem 生命周期入口。预注册全部骨架模板(早于任何端点的快照捕获/应用):debuff(RegisterDebuffSkeletonTemplates)、FX(FxHost/FxHost_CPU/FxEntity)、ProjectileHost、LootHost、ActorHost/SoundHost/AgentHost(均为幂等注册);随后 InitializeSnapshotTcpTransport() 按网络角色初始化 TCP 快照传输。

USubsystem lifecycle entry. Pre-registers all skeleton templates (before any snapshot capture/apply on any peer): debuffs (RegisterDebuffSkeletonTemplates), FX (FxHost/FxHost_CPU/FxEntity), ProjectileHost, LootHost, ActorHost/SoundHost/AgentHost (all idempotent); then InitializeSnapshotTcpTransport() initializes the TCP snapshot transport for the current net role.

Input
参数 Param类型 Type说明 Description
CollectionFSubsystemCollectionBase&子系统集合,由引擎传入。Subsystem collection provided by the engine.
Output

无返回值。副作用:快照模板注册表出现全部骨架 Key;按网络角色创建 TCP 传输(服务器监听,客户端绑定回调)。

No return value. Side effects: the snapshot template registry gains all skeleton keys; TCP transport is created per net role (server listens, client binds callbacks).

Deinitialize virtual void

USubsystem 生命周期出口:ShutdownSnapshotTcpTransport() 关闭并释放 TCP 传输对象,再调用父类实现。

USubsystem lifecycle exit: ShutdownSnapshotTcpTransport() shuts down and frees the TCP transport object, then calls the parent implementation.

Input

无参数。

No parameters.

Output

无返回值。副作用:TCP 传输关闭并置空。

No return value. Side effect: TCP transport shut down and nulled.

静态访问器与守卫 Static Accessors & Guard

GetPtr static UMassBattleNetworkSubsystem*

静态访问器:WorldContext 为空或 GetWorld() 为空时返回 nullptr;否则取其 Network 子系统。

Static accessor: returns nullptr when WorldContext is null or GetWorld() is null; otherwise returns the world's Network subsystem.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*任意 UObject 世界上下文。Any UObject world context.
Output

返回子系统指针;世界不可得时返回 nullptr。

Returns the subsystem pointer, or nullptr when the world is unavailable.

GetRef static UMassBattleNetworkSubsystem&

静态访问器的引用版本:失败即 check 断言崩溃——用于「子系统必须存在」的不变式场景。

Reference version of the static accessor: fails via check assertion — for invariant paths where the subsystem must exist.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*任意 UObject 世界上下文。Any UObject world context.
Output

返回子系统引用;取不到时触发 check 断言。

Returns a subsystem reference; triggers a check assertion when unavailable.

IsOffLockstep static bool

锁步外守卫:网络模式且当前不在锁步命令执行窗口(!IsInCommandExecution() 且 !IsInSnapshotRestore())时为真。public spawn API 用它区分"确定性命令路径调用"(放行——开发者可把任意函数接到自定义 CommandTag)与"任意帧 BP/C++ 调用"(拦截——会污染全局 UID 游标)。resync 重建窗口(bSnapshotRestoreContext)是刻意例外。

Off-lockstep guard: true when in networked mode and currently OUTSIDE the lockstep command-execution window (!IsInCommandExecution() and !IsInSnapshotRestore()). Public spawn APIs use it to separate deterministic command-path calls (allowed — developers wire arbitrary functions to their own CommandTags) from arbitrary-frame BP/C++ calls (blocked — would pollute the global UID cursor). The resync restore window (bSnapshotRestoreContext) is an intentional exception.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*任意 UObject 世界上下文。Any UObject world context.
Output

返回是否为锁步外调用;非网络模式或子系统缺失时返回 false。无副作用。由任务工厂(如 UMassBattleBPTaskAgentsMoveTo)做锁步门控。

Returns whether the call is off-lockstep; false when not in networked mode or the subsystem is missing. No side effects. Used as the lockstep gate by task factories (e.g. UMassBattleBPTaskAgentsMoveTo).

指令队列 Command Queue

EnqueueNetCommand void

入队一条网络指令(客户端输入转发、服务器汇聚、GameState 补发等入口)。按 MakeExecutedNetCommandKey(PlayerIndex/ExecuteTick/CommandTag/ServerExecSequence 的 CityHash64 组合)去重——已执行过的 key 或已在 pending 中的同 key 指令直接丢弃;随后按 (ExecuteTick 升序,同 tick 按 ServerExecSequence 升序) 有序插入,保证确定性执行顺序;同时追加进 ReceivedCommands 历史(供本地恢复 gap 填充)。

Enqueues a network command (client input forwarding, server convergence, GameState replay, etc.). Deduplicates by MakeExecutedNetCommandKey (CityHash64 over PlayerIndex/ExecuteTick/CommandTag/ServerExecSequence) — keys already executed or already pending are dropped; then inserts in order (ExecuteTick ascending, ServerExecSequence ascending within a tick) for a deterministic execution order; also appends to the ReceivedCommands history (for local-recovery gap filling).

Input
参数 Param类型 Type说明 Description
Cmdconst FMassBattleNetCommand&待入队指令(含 ExecuteTick/CommandTag/ServerExecSequence 等排序键)。Command to enqueue (carries the ordering keys ExecuteTick/CommandTag/ServerExecSequence).
Output

无返回值。副作用:指令按确定性序写入 PendingNetCommands 并追加 ReceivedCommands;重复 key 静默丢弃。

No return value. Side effects: the command lands in PendingNetCommands in deterministic order and is appended to ReceivedCommands; duplicate keys are silently dropped.

DequeueNetCommandsForTick TArray<FMassBattleNetCommand>

取回本 tick 到期的全部指令(由 UMassBattleSubsystem::Tick 锁步命令执行循环调用,置于 bInCommandExecution 窗口内)。含三个行为:① 每 1024 tick 执行一次账本裁剪(ExecutedCommandKeyToTick 与 ReceivedCommands 丢弃超过 2048 tick 的旧条目,防止无界增长);② 零容忍迟到策略——任何 ExecuteTick < CurrentTick 的指令一律无差别跳过并置 bOutHadLateCommands(无 tag 特权、无例外):迟到即失步,调用方必须转入失步恢复;绝不允许补放到更晚的 tick——延迟施加会与服务器在原 tick 的执行静默发散(旧签名"无故失步、local 恢复能修好"即由此而来);③ 已执行 key 跳过,未执行 key 记录后加入返回数组。注:旧的 bTolerateLate 容忍参数(PauseForServerToCatchUp 恢复路径补放迟到指令)已在 1.19.20 移除。

Dequeues all commands due for the current tick (called by the lockstep command-execution loop in UMassBattleSubsystem::Tick, inside the bInCommandExecution window). Three behaviors: ① ledger pruning every 1024 ticks (ExecutedCommandKeyToTick and ReceivedCommands drop entries older than 2048 ticks to bound growth); ② zero-tolerance late policy — any command with ExecuteTick < CurrentTick is skipped uniformly and flags bOutHadLateCommands (no tag privilege, no exceptions): late = desync, and the caller MUST route to desync recovery; never replay at a later tick — deferred application silently diverges from the server's execution at the original tick (source of the old "causeless desync, local resync fixes it" signature); ③ already-executed keys are skipped, new keys are recorded and added to the result. Note: the old bTolerateLate parameter (replaying late commands on the PauseForServerToCatchUp resume path) was removed in 1.19.20.

Input
参数 Param类型 Type说明 Description
CurrentTickint32当前模拟 tick;ExecuteTick ≤ CurrentTick 的指令到期。Current simulation tick; commands with ExecuteTick ≤ CurrentTick are due.
bOutHadLateCommandsbool&输出:本 tick 是否出现被跳过/判迟到的指令。Output: whether any command was skipped/judged late this tick.
Output

返回本 tick 待执行的指令数组(顺序 = 队列序);无到期指令返回空数组。副作用:裁剪账本、记录已执行 key、从 PendingNetCommands 移除已取出的前缀段。

Returns the commands to execute this tick (queue order); empty when none are due. Side effects: prunes the ledgers, records executed keys, and removes the dequeued prefix from PendingNetCommands.

CopyReceivedCommandsRange TArray<FMassBattleNetCommand>

从 ReceivedCommands 历史拷贝半开区间 [MinExecuteTick, MaxExecuteTick) 的指令——本地恢复(TryLocalSnapshotRecovery/ProcessDeferredSnapshot 的 GapCommands 补全)、晚加入与 resync gap 填充的消费者。

Copies commands in the half-open range [MinExecuteTick, MaxExecuteTick) from the ReceivedCommands history — consumed by local recovery (TryLocalSnapshotRecovery/ProcessDeferredSnapshot GapCommands filling), late-join and resync gap fill.

Input
参数 Param类型 Type说明 Description
MinExecuteTickint32区间下界(含)。Range lower bound (inclusive).
MaxExecuteTickint32区间上界(不含)。Range upper bound (exclusive).
Output

返回区间内指令的拷贝(原始顺序);无命中返回空数组。无副作用。

Returns a copy of the commands in range (original order); empty when nothing matches. No side effects.

lockstep 数据块 Block Transport

AllocServerBlockId / AllocLocalBlockId int32 (inline)

BlockId 分配器(头文件内联):AllocServerBlockId 自 NextServerBlockId 递增(服务器权威,从 1 起);AllocLocalBlockId 自 NextLocalBlockId 递增(客户端上行本地编号,从 1 起)。

BlockId allocators (inline in the header): AllocServerBlockId increments NextServerBlockId (server-authoritative, starts at 1); AllocLocalBlockId increments NextLocalBlockId (client-uplink local numbering, starts at 1).

Input

无参数。

No parameters.

Output

返回下一个 BlockId。副作用:对应计数器 +1。

Returns the next BlockId. Side effect: the matching counter increments.

StoreReceivedBlock void

把收到的(下行或汇聚)数据块按权威 BlockId 存入 ReceivedLockstepDataBlocks,记录执行 tick 与到达墙钟。

Stores a received (downlink or converged) block into ReceivedLockstepDataBlocks by authoritative BlockId, recording the execute tick and arrival wall-clock.

Input
参数 Param类型 Type说明 Description
BlockIdint32权威块编号。Authoritative block ID.
DataTArray<uint8>解压后的负载字节(移动语义写入)。Decompressed payload bytes (moved in).
ExecuteTickint32引用命令的执行 tick。Execute tick of the reference command.
Output

无返回值。副作用:覆写或新建该 BlockId 的缓存条目。同 BlockId 重复到达会被覆盖。

No return value. Side effect: overwrites or creates the cache entry for the BlockId. A repeated arrival overwrites.

FindReceivedBlock const FReceivedLockstepDataBlock*

按权威 BlockId 查找已接收数据块。

Finds a received block by authoritative BlockId.

Input
参数 Param类型 Type说明 Description
BlockIdint32权威块编号。Authoritative block ID.
Output

返回块指针;未找到返回 nullptr。

Returns the block pointer, or nullptr when not found.

FindUploadedBlock const FReceivedLockstepDataBlock*

按 [PlayerSlot][LocalBlockId] 查找客户端上行暂存块。

Finds a client-uplink staged block by [PlayerSlot][LocalBlockId].

Input
参数 Param类型 Type说明 Description
PlayerSlotint32客户端槽位。Client slot.
LocalBlockIdint32客户端本地块编号。Client-local block ID.
Output

返回块指针;未找到返回 nullptr。

Returns the block pointer, or nullptr when not found.

RemoveReceivedBlock void

移除已接收块(ExecuteNetCommand 消费块后由调用方调用)。

Removes a received block (called after ExecuteNetCommand consumes the block).

Input
参数 Param类型 Type说明 Description
BlockIdint32权威块编号。Authoritative block ID.
Output

无返回值。副作用:删除缓存条目(不存在则无操作)。

No return value. Side effect: deletes the cache entry (no-op when absent).

RemoveUploadedBlock void

消费并移除已上传的上行块;该槽位清空后删除槽位映射。

Consumes and removes an uploaded uplink block; removes the slot map once it empties.

Input
参数 Param类型 Type说明 Description
PlayerSlotint32客户端槽位。Client slot.
LocalBlockIdint32客户端本地块编号。Client-local block ID.
Output

无返回值。副作用:删除条目;空槽位整槽移除。

No return value. Side effects: deletes the entry; empty slots are removed entirely.

StagePendingBlockCommand void

暂存等待其 TCP 块的上行引用命令(服务器,High-1 竞态修复)——块比命令先到之外的反向竞态:命令先到则暂存,块到达时汇聚。

Stages an uplink reference command waiting for its TCP block (server, High-1 race fix) — the inverse race where the command arrives before its block: the command is staged and converges on block arrival.

Input
参数 Param类型 Type说明 Description
PlayerSlotint32客户端槽位。Client slot.
LocalBlockIdint32客户端本地块编号。Client-local block ID.
Cmdconst FMassBattleNetCommand&待暂存的引用命令。The reference command to stage.
Output

无返回值。副作用:写入 PendingBlockCommands 并记录暂存时间。

No return value. Side effect: writes into PendingBlockCommands with a staging timestamp.

TakePendingBlockCommand bool

取出并移除暂存命令(块到达汇聚时调用);槽位清空后整槽移除。

Removes and returns a staged command (called at block-arrival convergence); empty slots are removed entirely.

Input
参数 Param类型 Type说明 Description
PlayerSlotint32客户端槽位。Client slot.
LocalBlockIdint32客户端本地块编号。Client-local block ID.
OutCmdFMassBattleNetCommand&输出:被取出的命令。Output: the command taken out.
Output

返回是否成功取出;槽位或命令不存在返回 false 且 OutCmd 不保证有效。副作用:删除暂存条目。

Returns whether a command was taken; false (and OutCmd unspecified) when the slot or entry is missing. Side effect: deletes the staged entry.

StageLocalUplinkBlock void

监听服务器主机的"上行"暂存(1.19.20 新增):主机按设计没有客户端 TCP socket(共享服务器模拟),其自动分流路径调用本函数把块直接暂存进已上传缓存——与 TCP 上行回调(OnLockstepDataBlockUploaded)写入同一入口,结构与键完全一致,ConvergeUplinkBlock 像对待远程玩家 TCP 上行一样对待主机。由 AMassBattleNetworkPlayerControllerBase 调用(:80)。

Listen-server HOST "uplink" staging (new in 1.19.20): the host has no client TCP socket by design (it shares the server sim), so its auto-flood path calls this to stage the block directly into the uploaded cache — the same entry the TCP uplink callback (OnLockstepDataBlockUploaded) writes, with identical structure and keying, so ConvergeUplinkBlock treats the host exactly like a remote player's TCP upload. Called by AMassBattleNetworkPlayerControllerBase (:80).

Input
参数 Param类型 Type说明 Description
PlayerSlotint32客户端(此处为主机)槽位。Client (here: the host) slot.
BlockIdint32本地块编号。Local block ID.
DecompressedDataconst TArray<uint8>&解压后的负载字节(拷贝写入)。Decompressed payload bytes (copied in).
ExecuteTickint32引用命令的执行 tick。Execute tick of the reference command.
Output

无返回值。副作用:写入 UploadedLockstepDataBlocks[PlayerSlot][BlockId] 并记录到达墙钟。

No return value. Side effect: writes UploadedLockstepDataBlocks[PlayerSlot][BlockId] with an arrival timestamp.

StageBlockWaitCommand void

【修复 2026-08-29·块竞态失步】客户端下行块命令的"块未到"暂存等待:UDP 引用命令(引擎复制)与 TCP 数据块(自建传输)是两条独立发送路径,服务器卡顿恢复后两者 flush 顺序无保证——引用命令先到、块未到时,旧代码直接丢弃命令(客户端永久缺失该命令效果,只有服务器快照能修)。现在:暂存命令(对暂存列表按 MakeExecutedNetCommandKey 去重,防重投递产生孪生)+ 由调用方冻结本地 tick 推进,块到达后在同一 tick 号执行——与服务器序列完全一致;超时(10s,如 TCP 断链)才 RecordDesync 并 fail loud。由 AMassBattleNetworkGameStateBase 在块缺失时调用(:574)。与 Uplink 的 ConvergeUplinkBlock stage-&-wait 同款先例。

[FIX 2026-08-29 block-race desync] Client-side stage-and-wait for block commands whose TCP data has not arrived yet: the UDP reference command (engine replication) and the TCP data block (custom transport) are two INDEPENDENT send paths — a server stall recovers them in arbitrary order. When the reference arrives first, the OLD code silently dropped the command (the client permanently missed its effects; only a server snapshot rebuilds it). Now: the command is staged (deduped against the staged list by MakeExecutedNetCommandKey so re-delivery cannot twin) + the caller freezes local tick advancement; the command executes at the SAME tick number once the block lands — identical sequence to the server; only a timeout (10s, e.g. dead TCP) RecordDesyncs, failing loud. Called by AMassBattleNetworkGameStateBase when the block is missing (:574). Mirrors the uplink ConvergeUplinkBlock stage-&-wait.

Input
参数 Param类型 Type说明 Description
Cmdconst FMassBattleNetCommand&块未到的引用命令(其 DataBlockId 是等待键)。The reference command whose block is missing (its DataBlockId is the wait key).
Output

无返回值。副作用:追加 StagedBlockCommands 并记录暂存墙钟;输出 [BLOCK_WAIT] Warning 日志。

No return value. Side effects: appends to StagedBlockCommands with a staging timestamp; emits a [BLOCK_WAIT] warning log.

FlushStagedBlockCommands bool

重试全部暂存块命令:块到达(FindReceivedBlock 命中)→ 在冻结的 tick 号上执行(置 bInCommandExecution 窗口,经 GameState::ExecuteNetCommand + OnNetCommandExecuted 广播)并手动盖已执行键(本路径不经出队);超时(10s)→ RecordDesync 并丢弃命令(fail loud)。仍有暂存时返回 true——调用方据此冻结本地时间线。由 UMassBattleSubsystem::Tick 每帧调用(:1401,与 FlushStagedSpawnCommands 按位或)。

Retries every staged block command: block arrived (FindReceivedBlock hit) → execute at the frozen tick number (inside the bInCommandExecution window, via GameState::ExecuteNetCommand + the OnNetCommandExecuted broadcast) and manually stamp the executed key (this path bypasses the dequeue); timed out (10s) → RecordDesync and drop the command (fail loud). Returns true while any command remains staged — the caller freezes the local timeline on it. Called every frame by UMassBattleSubsystem::Tick (:1401, bitwise-OR'd with FlushStagedSpawnCommands).

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统。Main sim subsystem.
Output

返回是否仍有暂存命令(true = 调用方须冻结本地时间线)。副作用:执行已到块命令或超时丢弃。

Returns whether any command remains staged (true = the caller must freeze the local timeline). Side effects: executes landed commands or drops timed-out ones.

StageSpawnWaitCommand void

【修复 2026-09-07·生成延迟失步】*Component.Spawn / Obstacle.Spawn 命令目标宿主组件未复制时的客户端暂存等待:旧的 DeferOrDropSpawnCommand 路径把 ExecuteTick 每次重试 +3(仅在落后端)——服务器在 tick E 生成、客户端 E+3k 才生成,最新实体两端成员集合错开 3k tick(晚加入排查:恰为最新 8 实体的瞬态全体哈希毛刺,发生在追赶 FF 终点)。现在:暂存命令(同款按 key 去重)+ 冻结本地 tick 推进,组件复制到达后在同一 tick 号执行;超时(10s,如 actor 在途销毁)才 RecordDesync。由 AMassBattleNetworkGameStateBase 在宿主缺失时调用(:634/:700/:750/:955/:968/:980)。

[FIX 2026-09-07 spawn-defer desync] Client-side stage-and-wait for *Component.Spawn / Obstacle.Spawn commands whose target host component has not replicated yet: the OLD defer path (DeferOrDropSpawnCommand) rebased ExecuteTick +3 per retry on the LAGGING peer only — the server spawned at tick E while the client spawned at E+3k, so the newest entities were missing from one peer's per-tick hash for 3k ticks (late-join hunts: exactly the newest 8 uids, transient whole-army hash blips at the chase-FF endpoint). Now: the command is staged (same key dedup) + local tick advancement freezes; it executes at the SAME tick number once the component replicates; only a timeout (10s, e.g. an actor destroyed in flight) RecordDesyncs. Called by AMassBattleNetworkGameStateBase when the host is missing (:634/:700/:750/:955/:968/:980).

Input
参数 Param类型 Type说明 Description
Cmdconst FMassBattleNetCommand&宿主未复制的生成命令(等待键:*Component.Spawn 取 IntPayload[0]、Obstacle.Spawn 取 IntPayload[2] 的宿主 NetID)。The spawn command whose host has not replicated (wait key: the host NetID at IntPayload[0] for *Component.Spawn, IntPayload[2] for Obstacle.Spawn).
Output

无返回值。副作用:追加 StagedSpawnCommands 并记录暂存墙钟;输出 [SPAWN_WAIT] Warning 日志。

No return value. Side effects: appends to StagedSpawnCommands with a staging timestamp; emits a [SPAWN_WAIT] warning log.

FlushStagedSpawnCommands bool

重试全部暂存生成命令:宿主组件已复制(FindLockstepHost 命中)→ 在冻结的 tick 号上执行(同块冲刷契约:置 bInCommandExecution、经 GameState::ExecuteNetCommand、手动盖已执行键);超时(10s)→ RecordDesync 并丢弃。仍有暂存时返回 true(调用方冻结本地时间线)。由 UMassBattleSubsystem::Tick 每帧调用(:1401)。

Retries every staged spawn command: host component replicated (FindLockstepHost hit) → execute at the frozen tick number (same contract as the block flush: inside bInCommandExecution, via GameState::ExecuteNetCommand, executed key stamped manually); timed out (10s) → RecordDesync and drop. Returns true while any command remains staged (the caller freezes the local timeline). Called every frame by UMassBattleSubsystem::Tick (:1401).

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统。Main sim subsystem.
Output

返回是否仍有暂存命令。副作用:执行已复制宿主的生成命令或超时丢弃。

Returns whether any command remains staged. Side effects: executes commands whose hosts have replicated or drops timed-out ones.

RequeueCommandsFront void

把未执行的到期命令按序插回队头:出队循环在暂存块命令处中断,同 tick 的后继命令不得先于它执行(服务器序为 (ExecuteTick, ServerExecSequence))——待暂存命令执行后它们重新出队。实现为逆序头部插入(恢复原执行顺序),同时移除各命令的已执行键(出队在调用方执行之前就盖键,带旧键重新出队会被当已执行跳过删除、永不执行)。由 UMassBattleSubsystem::Tick 的暂存等待路径调用(:1457/:1832)。

Puts un-executed due commands back at the queue HEAD (in order): the dequeue loop stops at a staged block command; its successors in the SAME tick must not run before it (server order is (ExecuteTick, ServerExecSequence)) — they re-dequeue after the staged command executes. Implemented as reverse head-insertion (restoring the exact original order), also removing each command's executed-key (the dequeue stamps keys BEFORE the caller executes; a re-dequeued stamped key would be skipped-and-deleted as an already-executed duplicate, never running). Called by the staged-wait path in UMassBattleSubsystem::Tick (:1457/:1832).

Input
参数 Param类型 Type说明 Description
Cmdsconst TArray<FMassBattleNetCommand>&按执行序传入的待插回命令。Commands to re-insert, in execution order.
Output

无返回值。副作用:头部插入 PendingNetCommands 并移除对应已执行键。

No return value. Side effects: head-inserts into PendingNetCommands and removes the matching executed keys.

PruneStaleBlocks void

丢弃超过 30 秒宽限窗的未消费块(防泄漏;块应在 K-buffer tick 内消费)。对三个 map 统一清理:ReceivedLockstepDataBlocks、UploadedLockstepDataBlocks、PendingBlockCommands;空槽位整槽移除。

Drops unconsumed blocks past the 30-second grace window (anti-leak; blocks should be consumed within K-buffer ticks). Cleans all three maps uniformly: ReceivedLockstepDataBlocks, UploadedLockstepDataBlocks, PendingBlockCommands; empty slots are removed entirely.

Input

无参数(基于各条目的 ReceiveTime 与当前墙钟)。

No parameters (based on each entry's ReceiveTime versus the current wall-clock).

Output

无返回值。副作用:删除超龄条目。由 TickSnapshotTcpTransport 每次调用时触发。

No return value. Side effect: deletes aged-out entries. Triggered by every TickSnapshotTcpTransport call.

PackLockstepPayload static TArray<uint8>

把四个 payload 数组(FName/int32/float/uint8)打包为字节 blob,供 TCP 块传输。FName 经 FString 中转——FName 索引是进程内的,不跨机器可移植。顺序:Names → Ints → Floats → Bytes。

Packs the four payload arrays (FName/int32/float/uint8) into a byte blob for TCP block transport. FName round-trips via FString — FName entry indices are per-process and not portable across machines. Order: Names → Ints → Floats → Bytes.

Input
参数 Param类型 Type说明 Description
Namesconst TArray<FName>&FName 数组。FName array.
Intsconst TArray<int32>&int32 数组。int32 array.
Floatsconst TArray<float>&float 数组。float array.
Bytesconst TArray<uint8>&原始字节数组。Raw byte array.
Output

返回打包后的字节 blob。无副作用。

Returns the packed byte blob. No side effects.

UnpackLockstepPayload static bool

把字节 blob 反解回四个 payload 数组(与 PackLockstepPayload 镜像)。空 blob 或读错误返回 false;FString 转回 FName。

Unpacks a byte blob back into the four payload arrays (mirror of PackLockstepPayload). Returns false on an empty blob or a read error; FStrings convert back to FNames.

Input
参数 Param类型 Type说明 Description
Blobconst TArray<uint8>&打包的字节 blob。The packed byte blob.
OutNamesTArray<FName>&输出:FName 数组。Output: FName array.
OutIntsTArray<int32>&输出:int32 数组。Output: int32 array.
OutFloatsTArray<float>&输出:float 数组。Output: float array.
OutBytesTArray<uint8>&输出:原始字节数组。Output: raw byte array.
Output

返回是否反解成功(空 blob 或 FMemoryReader 错误 → false,输出参数不保证有效)。副作用:写入四个输出数组。

Returns whether unpacking succeeded (empty blob or FMemoryReader error → false, outputs unspecified). Side effect: fills the four output arrays.

EstimatePayloadSize static int32 (inline)

序列化负载大小的粗略保守估算(字节):Names.Num() × 16 + Ints.Num() × sizeof(int32) + Floats.Num() × sizeof(float) + Bytes.Num()。用于自动分流阈值比较。

Rough conservative estimate of the serialized payload size (bytes): Names.Num() × 16 + Ints.Num() × sizeof(int32) + Floats.Num() × sizeof(float) + Bytes.Num(). Used for the auto-flood threshold comparison.

Input
参数 Param类型 Type说明 Description
Namesconst TArray<FName>&FName 数组。FName array.
Intsconst TArray<int32>&int32 数组。int32 array.
Floatsconst TArray<float>&float 数组。float array.
Bytesconst TArray<uint8>&原始字节数组。Raw byte array.
Output

返回估算字节数。纯函数,无副作用。

Returns the estimated byte count. Pure, no side effects.

GetAutoFloodSwitchBytes static int32

读取 CVar MassBattle.AutoFloodSwitchBytes(默认 16384)——超过该阈值的 lockstep 命令从 UDP RPC 切到 TCP 块 + 引用命令;0 = 从不切换(始终 UDP)。

Reads the CVar MassBattle.AutoFloodSwitchBytes (default 16384) — lockstep commands whose payload exceeds the threshold switch from UDP RPC to TCP block + reference command; 0 = never switch (always UDP).

Input

无参数。

No parameters.

Output

返回当前阈值(字节)。

Returns the current threshold in bytes.

哈希与快照 Hash + Snapshot

HasCachedLatestSnapshot bool (const)

判断是否已缓存最新快照(CachedLatestSnapshot 指针有效且 Entities 非空)。由 AMassBattleNetworkGameModeBase 在发快照前检查。

Checks whether the latest snapshot is cached (the CachedLatestSnapshot pointer is valid and Entities is non-empty). Checked by AMassBattleNetworkGameModeBase before sending a snapshot.

Input

无参数。

No parameters.

Output

返回是否已有缓存快照。

Returns whether a cached snapshot exists.

RecordDesync void

记录一次失步:LastDesyncTick = TickCount,TotalDesyncCount++。由 UMassBattleSubsystem::Tick(服务器端哈希失配)、AMassBattleNetworkGameModeBase(ack 失配/迟到)与 AMassBattleNetworkGameStateBase(延迟失步检查)调用。

Records a desync: LastDesyncTick = TickCount, TotalDesyncCount++. Called by UMassBattleSubsystem::Tick (server-side hash mismatch), AMassBattleNetworkGameModeBase (ack mismatch/late) and AMassBattleNetworkGameStateBase (deferred desync checks).

Input
参数 Param类型 Type说明 Description
TickCountint32失步发生的模拟 tick。Simulation tick where the desync happened.
Output

无返回值。副作用:更新两个公开计数成员。

No return value. Side effects: updates the two public counter members.

TryGetServerHashForTick bool (const)

从 ServerHashHistory 查指定 tick 的服务器哈希。FF 完成块在 EvaluateDeferredDesyncChecks 后紧随读取(当前 tick 条目经严格 < 裁剪存活)。

Looks up the server hash for a tick in ServerHashHistory. Read by the FF-completion block right after EvaluateDeferredDesyncChecks (strict-< trimming keeps the current-tick entry alive).

Input
参数 Param类型 Type说明 Description
TickCountint32查询 tick。Tick to query.
OutHashint64&输出:服务器哈希。Output: the server hash.
Output

返回是否命中;未命中时 OutHash 置 0 并返回 false。

Returns whether the tick was found; on a miss OutHash is set to 0 and false is returned.

SetServerSyncState void

写入服务器同步状态:更新 ServerTickCount 与 ServerTimeDilation;LastKnownInputBufferMs 仅在输入值 > 0 时更新(保持旧值防抖动)。由 AMassBattleNetworkGameStateBase 在接收服务器同步 tick 时调用。

Writes server sync state: updates ServerTickCount and ServerTimeDilation; LastKnownInputBufferMs updates only when the input is > 0 (keeps the old value to avoid jitter). Called by AMassBattleNetworkGameStateBase when a server sync tick arrives.

Input
参数 Param类型 Type说明 Description
InServerTickint32服务器当前 tick。Server's current tick.
InputBufferMsfloat服务器报告的输入缓冲(毫秒);≤ 0 时保持旧值。Server-reported input buffer (ms); values ≤ 0 keep the old value.
TimeDilationfloat服务器时间膨胀比率。Server time dilation ratio.
Output

无返回值。副作用:更新三个调速输入成员。

No return value. Side effects: updates the three pacing input members.

CacheLatestSnapshot void

组装并缓存最新快照(由 UMassBattleSubsystem::Tick 在 OnTickCompleted 广播前调用)。流程:① EntitySnapshotBuffer.Merge() 合并并行收集的实体快照记录,按 UniqueID 排序保证 payload 顺序确定性;② 盖 TickCount(捕获 tick 末状态)与 ServerHashAtCapture(本端 LastTickHash);③ 采集待执行命令(ExecTick ≥ TickCount)、deferred agent spawn 队列(锁内拷贝,仅网络模板)、UIDOccupiedCount(UID 分配器占用计数指纹)、Agent/HashGrid 随机流、BP 任务记录与任务 ID 计数器、LockstepVarStore(PendingVarStoreSnapshot 移入);④ 存入 ValidatedSnapshots 验证环缓冲(槽 0 永不覆盖);⑤ 事后交叉验证——若 ServerHashHistory 已有同 tick 哈希且与本端一致,补盖章。

Assembles and caches the latest snapshot (called by UMassBattleSubsystem::Tick before the OnTickCompleted broadcast). Flow: ① EntitySnapshotBuffer.Merge() merges the parallel-gathered entity snapshot records, sorted by UniqueID for deterministic payload order; ② stamps TickCount (end-of-tick state) and ServerHashAtCapture (this peer's LastTickHash); ③ captures pending commands (ExecTick ≥ TickCount), the deferred agent spawn queue (copy under lock, networked templates only), UIDOccupiedCount (UID-allocator occupied-count fingerprint), the Agent/HashGrid random streams, BP task records and task-ID counters, and LockstepVarStore (moved from PendingVarStoreSnapshot); ④ stores into the ValidatedSnapshots validation ring buffer (slot 0 never overwritten); ⑤ post-hoc cross-validation — if ServerHashHistory already has the same-tick hash matching the local one, the snapshot is stamped.

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统,提供 tick/UID 映射/随机流/任务记录等采集源。Main sim subsystem providing tick/UID maps/random streams/task records as capture sources.
Output

无返回值。副作用:覆写 CachedLatestSnapshot、清空 EntitySnapshotBuffer、写入验证环缓冲、清空 PendingVarStoreSnapshot。无实体记录时提前返回(不更新快照)。

No return value. Side effects: overwrites CachedLatestSnapshot, empties EntitySnapshotBuffer, writes the validation ring buffer, and clears PendingVarStoreSnapshot. Returns early (no snapshot update) when no entity records exist.

RetireSnapshotEntitiesAsync void

【2026-08-30 性能·v2】把被替换的快照记录(数万~十几万 per-fragment blob TArray,如 7000 实体 ≈ 17.5 万次 heap free)整批移交后台任务析构——纯 POD/数组、无 UObject,默认分配器线程安全。历史:一次性串行析构曾是每 NetworkFlushIntervalTicks tick 一次 10-30ms 卡顿(落在 NetworkProcessor 与 TickCpuInterp 之间);v1 分片退休(每帧消化一片 512 条)追不上追加速率(每次捕获 7 千条),队列无界膨胀;v2 改为整批后台析构。由 CacheLatestSnapshot 在替换 CachedLatestSnapshot 与覆写验证环槽位时调用(:1833/:1865)。

[2026-08-30 perf v2] Retires replaced snapshot records (tens of thousands of per-fragment blob TArrays — 175k heap frees at 7k entities) by moving the whole destructor storm onto a background task — POD/arrays only, no UObjects; the default allocator is thread-safe. History: the one-shot serial destructor used to cost a 10-30ms hitch every NetworkFlushIntervalTicks tick (landing between the NetworkProcessor span and TickCpuInterp); the v1 sliced retirement (512 records drained per frame) could never keep up with the append rate (7k records per capture), so the queue grew unbounded; v2 hands the whole batch to the background. Called by CacheLatestSnapshot when replacing CachedLatestSnapshot and overwriting ring slots (:1833/:1865).

Input
参数 Param类型 Type说明 Description
RecordsTArray<FEntitySnapshotRecord>&&被退休的实体快照记录(移动语义,后台任务析构)。The retired entity snapshot records (moved; destructed on the background task).
Output

无返回值。副作用:后台任务异步释放记录内存。

No return value. Side effect: the records' memory is freed asynchronously on a background task.

ValidateSnapshotsAgainstServerHash void

用服务器哈希给环缓冲中未验证(ServerHash == 0)的快照盖章:本端哈希与服务器哈希一致即验证通过。由 AMassBattleNetworkGameStateBase 在 MulticastSyncTick 接收路径调用。

Stamps unvalidated (ServerHash == 0) snapshots in the ring buffer with the server hash: a snapshot whose local hash matches the server hash becomes validated. Called by AMassBattleNetworkGameStateBase on the MulticastSyncTick receive path.

Input
参数 Param类型 Type说明 Description
InTickCountint32服务器哈希所属 tick(当前实现仅用于日志语义,比对按哈希值)。Tick of the server hash (used for logging semantics only in the current implementation; comparison is by hash value).
ServerHashint64服务器哈希。The server hash.
MBUMassBattleSubsystem*主模拟子系统(当前实现未使用,预留)。Main sim subsystem (unused by the current implementation; reserved).
Output

无返回值。副作用:把匹配的快照 ServerHash 从 0 改为服务器哈希,使其可被本地恢复选用。

No return value. Side effect: matching snapshots get their ServerHash promoted from 0 to the server hash, making them eligible for local recovery.

QueueSnapshotApply bool

排队待应用快照:① 拒绝严格早于上次已成功应用 payload 的快照(PayloadTick < LastAppliedSnapshotPayloadTick)——回滚会致持续 resync 循环;允许相等 PayloadTick 重新应用(上次应用后 FF 发散,给服务器时间拍新快照);② 拒绝早于或等于当前排队中 payload 的快照;③ 通过则存入 PendingSnapshotPayload / PendingSnapshotTargetTick 并置 bPendingSnapshotApply。由客户端 TCP 回调与 TryLocalSnapshotRecovery 调用。

Queues a snapshot for application: ① rejects payloads strictly older than the last successfully applied one (PayloadTick < LastAppliedSnapshotPayloadTick) — rolling back would cause a persistent resync loop; equal PayloadTick is allowed to re-apply (the previous apply may have FF'd with divergence; this gives the server time to capture a newer snapshot); ② rejects payloads older than or equal to the currently queued one; ③ on acceptance stores into PendingSnapshotPayload / PendingSnapshotTargetTick and sets bPendingSnapshotApply. Called by the client TCP callback and TryLocalSnapshotRecovery.

Input
参数 Param类型 Type说明 Description
Payloadconst FEntitySnapshotPayload&完整快照载荷(其 TickCount 用于新旧判定)。Full snapshot payload (its TickCount drives the freshness checks).
TargetTickint32应用后追帧的目标 tick(-1 = 不追帧)。Fast-forward target tick after apply (-1 = no fast-forward).
Output

返回是否接受排队(过期快照返回 false)。副作用:覆写 pending 快照并置位标志。

Returns whether the snapshot was accepted (stale ones return false). Side effects: overwrites the pending snapshot and sets the flag.

TryLocalSnapshotRecovery bool

本地快照恢复主路径(server 快照为兜底),每次失步都重试:① 防重入——已有恢复在途(bPendingSnapshotApply/bSnapshotFastForward/bFastForwarding)直接返回 false;② 从验证环缓冲选最新且 ServerHash != 0、tick 龄 ≤ LagResyncThresholdTicks 的快照;③ 拷贝 payload 并从本地命令历史(CopyReceivedCommandsRange)补全 GapCommands(原快照的 GapCommands 只覆盖发送时的跨度);④ QueueSnapshotApply;⑤ 成功则置 bPendingLocalRecovery(来源意图标记)与 bSnapshotFastForward(应用后自动追帧);快照过期(被拒绝)时不锁 bSnapshotFastForward——否则永久为真并屏蔽后续失步恢复。

Primary local-snapshot recovery path (server snapshot is the fallback), retried on every desync: ① re-entrancy guard — returns false when a recovery is already in flight (bPendingSnapshotApply/bSnapshotFastForward/bFastForwarding); ② picks the newest snapshot in the validation ring buffer with ServerHash != 0 and tick age ≤ LagResyncThresholdTicks; ③ copies the payload and fills GapCommands from the local command history (CopyReceivedCommandsRange) — the original GapCommands only covered the span at send time; ④ QueueSnapshotApply; ⑤ on success sets bPendingLocalRecovery (source-intent flag) and bSnapshotFastForward (auto-FF after apply); on a stale (rejected) snapshot it must NOT latch bSnapshotFastForward — otherwise it stays true forever and blocks all future desync recovery.

Input
参数 Param类型 Type说明 Description
TargetTickint32应用后追帧的目标 tick。Fast-forward target tick after apply.
MBUMassBattleSubsystem*主模拟子系统(tick 龄计算等)。Main sim subsystem (tick-age computation etc.).
Output

返回是否已排队本地快照恢复(无可用已验证快照或已在恢复中 → false)。副作用:补全并排队快照、置位意图/追帧标志。

Returns whether local snapshot recovery was queued (no usable validated snapshot or recovery in flight → false). Side effects: fills and queues the snapshot, sets the intent/FF flags.

ApplyEntitySnapshotPayload bool

应用快照载荷——resync 的核心重建。主要阶段:① 重建顺序排序(EntityType 优先级 Agent→Debuff→Projectile/Loot→FxEntity→Host→Obstacle,类型内 UID 升序,索引数组避免深拷贝);② 模板解析——注册表命中,否则按 DA 路径 LoadObject 兜底链(agent → projectile → loot 独立 if 链,晚加入客户端也能 apply),重复 UniqueID 检查(fail loud);③ 清场——HashGrid.ResetOccupiedAgentCells() + DestroyQuery(全部 FNetworkTag 实体),销毁前先释放 UObject 组件(Fx/Actor/Sound 分支防孤儿特效与双份宿主);④ 重建循环——agent 分支从 blob 提取 Team、按模板 SubType 盖章、注入 shared fragment blob、应用 archetype tag 增量、剥离端侧本地渲染 flag(SnapshotStrippedRenderFlagsMask);非 agent 分支走骨架模板 + blob 恢复;两者都 RegisterUIDEntity;⑤ 恢复全局状态——UID 分配器经 ReconcileUIDAllocator 从重建映射收敛(位图不同步,占用计数仅为哈希指纹)、BP 任务 ID 计数器、Agent/HashGrid 随机流、LockstepVarStore;⑥ 命令合并——快照命令 + 握手窗口旧命令(ExecTick > PayloadTick)+ GapCommands,按 (ExecuteTick, ServerExecSequence) 排序,移除 ≤ payload tick 的命令,裁剪执行账本;⑦ 回滚 TickCount 与 SimulationTime(apply 按设计滞后捕获 1 tick,不回滚则客户端绝对时间基线永久领先);⑧ 逐实体 blob 恢复(全部字段策略,含 HandleFixups 解析);⑨ 池回填(ClearPoolArraysForRestore + ReturnPooledXxx 按 (类型,UID) 升序,与服务器 LIFO 弹池一致);⑩ deferred spawn 队列恢复、宿主 bNeedsSpawnRefresh 标记(已生成宿主重发组件 op,不重置 bSpawned 防双消费随机流)、运行时对象指针解析、LaunchGatherer.Reset()、验证环裁剪;⑪ 恢复哈希校验——重折叠全部重建实体与 VarStore,与 ServerHashAtCapture 比对,不匹配 fail loud 拒绝应用。

Applies a snapshot payload — the core rebuild of resync. Main phases: ① rebuild-order sort (EntityType priority Agent→Debuff→Projectile/Loot→FxEntity→Host→Obstacle, UID ascending within a type; index array avoids deep-copying blobs); ② template resolution — registry hit, otherwise a DA-path LoadObject fallback chain (agent → projectile → loot as independent if-chains so late-join clients can still apply), duplicate UniqueIDs fail loud; ③ teardown — HashGrid.ResetOccupiedAgentCells() + a DestroyQuery over all FNetworkTag entities, releasing UObject components first (Fx/Actor/Sound branches prevent orphaned FX and duplicate hosts); ④ rebuild loop — the agent branch extracts Team from the blob, stamps SubType per template, injects shared-fragment blobs, applies archetype tag deltas, and strips peer-local render flags (SnapshotStrippedRenderFlagsMask); the non-agent branch goes through skeleton templates + blob restore; both call RegisterUIDEntity; ⑤ restores global state — the UID allocator converges via ReconcileUIDAllocator from the rebuilt map (bitmap not synced; the occupied count is only a hash fingerprint), BP task-ID counters, Agent/HashGrid random streams, LockstepVarStore; ⑥ command merge — snapshot commands + handshake-window old commands (ExecTick > PayloadTick) + GapCommands, sorted by (ExecuteTick, ServerExecSequence), commands ≤ payload tick removed, execution ledger trimmed; ⑦ rolls back TickCount and SimulationTime (apply lags capture by 1 tick by design; without this the client's absolute-time baseline stays permanently ahead); ⑧ per-entity blob restore (all field policies, including HandleFixup resolution); ⑨ pool push-back (ClearPoolArraysForRestore + ReturnPooledXxx in (type, UID) ascending order, matching the server's UID-sorted LIFO pools); ⑩ deferred-spawn-queue restore, host bNeedsSpawnRefresh marking (only already-spawned hosts re-issue the component op; bSpawned is NOT reset to avoid double-consuming the random stream), runtime object-pointer resolution, LaunchGatherer.Reset(), validation-ring trimming; ⑪ restore-hash validation — re-folds all rebuilt entities and VarStores and compares against ServerHashAtCapture; a mismatch fails loud and rejects the apply.

Input
参数 Param类型 Type说明 Description
Payloadconst FEntitySnapshotPayload&快照载荷(实体记录、命令、全局状态、VarStore 等)。The snapshot payload (entity records, commands, global state, VarStores).
MBUMassBattleSubsystem*主模拟子系统(实体构建/UID 映射/随机流恢复)。Main sim subsystem (entity build / UID maps / random-stream restore).
Output

返回恢复是否成功(任何阶段失败——模板缺失、重复 UID、blob 越界、恢复哈希不匹配——均返回 false 并附 Error 日志,拒绝应用)。副作用:销毁并重建全部网络实体、覆写全局确定性状态、合并命令队列、回填池。由 ProcessDeferredSnapshot 调用。

Returns whether the restore succeeded (any phase failure — missing template, duplicate UID, blob overrun, restore-hash mismatch — returns false with an Error log and rejects the apply). Side effects: destroys and rebuilds all networked entities, overwrites global deterministic state, merges the command queue, refills pools. Called by ProcessDeferredSnapshot.

ProcessDeferredSnapshot void

处理排队的快照应用(由 UMassBattleSubsystem::Tick 在帧末/帧首调用,无 pending 时直接返回)。流程:① 本地恢复专用 apply 滞后补偿——本地恢复在 tick N 捕获 GapCommands=[T0,N) 而 apply 发生在 N+1,期间 dequeue 执行的 ≤ N+1 命令效果会被重建销毁,故在 apply 当刻用 CopyReceivedCommandsRange(PayloadTick, TickCount+1) 重新捕获(+1 因半开区间需含 ==N+1);② ApplyEntitySnapshotPayload 应用,成功则 ResyncGeneration++(渲染身份令牌,使 GPU resync 后跳变插值);③ 清空 pending 状态(防重入);④ 失败 → 向服务器报告失败结果并返回;⑤ 成功后:组件重链(LockstepRegistry 中全部 UMassBattleEntityComponentBase 的 RebindToEntity())、本地视觉宿主重挂(RebindLocalVisualsAfterResync)、BP 任务重建(在 bSnapshotRestoreContext 窗口内,任务工厂放行 IsOffLockstep);⑥ 若指定 TargetTick 则 BeginFastForward,否则只解除归属自己的暂停(epoch 校验);⑦ 向服务器报告成功。

Processes the queued snapshot apply (called by UMassBattleSubsystem::Tick; returns immediately when nothing is pending). Flow: ① apply-lag compensation for local recovery — TryLocalSnapshotRecovery captured GapCommands=[T0,N) at tick N but apply happens at N+1, and commands with ExecuteTick ≤ N+1 executed in between are destroyed by the rebuild, so it re-captures via CopyReceivedCommandsRange(PayloadTick, TickCount+1) at the actual apply tick (+1 because the half-open range must include ExecuteTick == N+1); ② ApplyEntitySnapshotPayload; on success ResyncGeneration++ (render identity token so the GPU snaps interpolation after resync); ③ clears pending state (re-entrancy safety); ④ on failure — reports the failure to the server and returns; ⑤ on success: component re-link (each UMassBattleEntityComponentBase in LockstepRegistry gets RebindToEntity()), peer-local visual host re-link (RebindLocalVisualsAfterResync), BP task rebuild (inside the bSnapshotRestoreContext window so task factories bypass IsOffLockstep); ⑥ with a TargetTick it calls BeginFastForward, otherwise it only releases a pause it owns (epoch check); ⑦ reports success to the server.

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统。Main sim subsystem.
Output

无返回值。副作用:应用快照、重链组件/视觉宿主、重建任务、追帧或解除暂停、经 ServerReportResyncResult 报告服务器。

No return value. Side effects: applies the snapshot, re-links components/visual hosts, rebuilds tasks, fast-forwards or releases the pause, and reports to the server via ServerReportResyncResult.

布局缓存 Layout Caches

GetOrBuildSnapshotLayout const FSnapshotFragmentLayout*

按 fragment 类型名取快照布局(缓存命中直接返回;TotalBlobSize ≤ 0 的缓存视为无效返回 nullptr)。未命中时经注册表宏(MB_SNAP_LAYOUT,拆成 BuildSnapshotLayoutPartA/B 两个静态助手规避 MSVC C4883)构建并缓存。冷路径,由处理器捕获与恢复端共用。

Returns the snapshot layout for a fragment type name (cache hit returns directly; cached layouts with TotalBlobSize ≤ 0 are treated as invalid and return nullptr). On a miss it builds via the registry macros (MB_SNAP_LAYOUT, split into the static helpers BuildSnapshotLayoutPartA/B to stay under MSVC's C4883) and caches. Cold path, shared by the processor capture side and the restore side.

Input
参数 Param类型 Type说明 Description
FragmentTypeNameFNamefragment 类型名(注册表中的名字)。Fragment type name (as listed in the registry).
Output

返回布局指针;未知类型或空布局返回 nullptr。副作用:首次访问构建并缓存布局(串行阶段调用,无并发插入)。

Returns the layout pointer, or nullptr for unknown types/empty layouts. Side effect: builds and caches the layout on first access (called from serial phases, no concurrent inserts).

PreBuildSnapshotLayoutCache void

预填全部快照布局(注册表宏遍历普通 + shared fragment 列表)——在所有并行工作之前执行,保证 TMap 指针稳定(无并发插入)。由 MassBattleNetworkProcessor 每帧进入并行段前调用。

Pre-populates all snapshot layouts (registry macros over the normal + shared fragment lists) — runs before any parallel work so TMap pointers stay stable (no concurrent inserts). Called by MassBattleNetworkProcessor before its parallel section each frame.

Input

无参数。

No parameters.

Output

无返回值。副作用:填充 SnapshotLayoutCache。

No return value. Side effect: fills SnapshotLayoutCache.

GetOrBuildHashLayout const FHashFragmentLayout*

按 fragment 类型名取哈希布局(缓存命中直接返回;Fields 空的缓存视为无效返回 nullptr)。未命中时经哈希注册表宏构建(MB_HASH_LAYOUT,逐类别列表)并缓存。由处理器 per-entity 折叠与恢复校验共用——两处必须保持同步。

Returns the hash layout for a fragment type name (cache hit returns directly; cached layouts with empty Fields are treated as invalid and return nullptr). On a miss it builds via the hash registry macros (MB_HASH_LAYOUT, per-category lists) and caches. Shared by the processor per-entity fold and the restore validation — both must stay in lockstep.

Input
参数 Param类型 Type说明 Description
FragmentTypeNameFNamefragment 类型名。Fragment type name.
Output

返回布局指针;未知类型或空布局返回 nullptr。副作用:首次访问构建并缓存布局。

Returns the layout pointer, or nullptr for unknown types/empty layouts. Side effect: builds and caches the layout on first access.

PreBuildHashLayoutCache void

预填全部哈希布局(处理器循环前;串行循环 + 预建 ⇒ 无并发插入)。由 MassBattleNetworkProcessor 每帧与 PreBuildSnapshotLayoutCache 成对调用。

Pre-populates all hash layouts (before the processor loop; serial loop + prebuild ⇒ no concurrent inserts). Called by MassBattleNetworkProcessor each frame paired with PreBuildSnapshotLayoutCache.

Input

无参数。

No parameters.

Output

无返回值。副作用:填充 HashLayoutCache。

No return value. Side effect: fills HashLayoutCache.

MixHashFragmentInto static void

把单个 fragment 的字段按布局逐字段折叠进 64 位哈希(RawBytes 原字节;float 结构规范化;-0.0→0.0;FRandomStream 取 seed;FEntityHandle 折叠目标 UID,经 MB->FindUIDByEntity 且无效 → -1,与 blob 序列化器一致——失效句柄残留映射时折叠残留 UID 会导致恢复端重折叠分叉,resync 卡死)。布局为空时静默返回(防御——注册表为唯一来源不会触发)。

Folds one fragment's fields into the 64-bit hash per layout (RawBytes as raw bytes; float structs canonicalized -0.0→0.0; FRandomStream folds its seed; FEntityHandle folds the target UID via MB->FindUIDByEntity with invalid → -1, matching the blob serializer — a stale handle lingering in the map would fold a stale UID while the blob serializes -1, diverging the restore-side re-fold and sticking resync at PauseForServerSnapshot). Silently returns on a null layout (defensive — the registry is the single source, so this never fires).

Input
参数 Param类型 Type说明 Description
Huint64&累加哈希(引用,就地折叠)。Accumulated hash (by reference, folded in place).
Layoutconst FHashFragmentLayout*哈希布局。The hash layout.
FragmentSrcconst uint8*fragment 内存基址。Fragment memory base pointer.
MBUMassBattleSubsystem*主模拟子系统,提供 UID 映射。Main sim subsystem providing the UID map.
Output

无返回值。副作用:修改 H。

No return value. Side effect: mutates H.

哈希历史 Hash History

TryGetTickHashForTick bool (const)

从 TickHashHistory 查指定 tick 的本端哈希。由 AMassBattleNetworkGameModeBase 的 ack 校验与 AMassBattleNetworkGameStateBase 的失步检查读取。

Looks up this peer's hash for a tick in TickHashHistory. Read by AMassBattleNetworkGameModeBase ack validation and AMassBattleNetworkGameStateBase desync checks.

Input
参数 Param类型 Type说明 Description
TargetTickint32查询 tick。Tick to query.
OutHashint64&输出:本端哈希。Output: this peer's hash.
Output

返回是否命中;未命中时 OutHash 置 0 并返回 false。

Returns whether the tick was found; on a miss OutHash is set to 0 and false is returned.

快进与失步 Fast-Forward & Desync

BeginFastForward void

开始追帧:目标已 ≤ 当前 tick 时无需追帧——必须清 bSnapshotFastForward(否则永久为真并屏蔽失步恢复;FF 完成清除受 bFastForwarding 门控,而本路径从不设置它)并解除归属自己的暂停。追帧进行中则取更大的目标 tick。首次进入:置 bFastForwarding、记录起止 tick、清零失配计数、保存并临时关闭 MB->bFrameSpreading,并按来源广播事件(本地快照/服务器快照/纯追帧)。

Begins fast-forward: when the target is ≤ the current tick no FF is needed — it MUST clear bSnapshotFastForward (otherwise it stays true forever and blocks desync recovery; the FF-completion clear is gated on bFastForwarding, which this path never sets) and releases the pause it owns. While FF is running it keeps the larger target tick. On first entry: sets bFastForwarding, records start/target ticks, zeroes mismatch counters, saves and temporarily disables MB->bFrameSpreading, and broadcasts the event by source (local snapshot / server snapshot / pure catch-up).

Input
参数 Param类型 Type说明 Description
TargetTickint32追帧目标 tick。Fast-forward target tick.
MBUMassBattleSubsystem*主模拟子系统(帧分散开关)。Main sim subsystem (frame-spread toggle).
Output

无返回值。副作用:置位/清除追帧标志、广播 OnNetworkEvent(FastForwardViaLocalSnapshot/FastForwardViaServerSnapshot/FastForwardCatchUp)、修改 MB->bFrameSpreading。

No return value. Side effects: sets/clears FF flags, broadcasts OnNetworkEvent (FastForwardViaLocalSnapshot/FastForwardViaServerSnapshot/FastForwardCatchUp), mutates MB->bFrameSpreading.

AbortFastForwardForSnapshot void

【2026-08-29·追帧中止】拆除进行中的追帧并转入服务器快照恢复,而非硬追数百 tick:追帧落后服务器活前沿超过 FastForwardAbortBehindTicks(如追帧途中本机卡顿掉队)时,倍速硬追要数分钟——中止并请求新快照,重建直接跳到服务器前沿附近,几 tick 即追完;FF 速率低于服务器推进速率(持续卡顿)时尤为重要。镜像追帧完成清理(减去完成广播与 FF tick 哈希校验),随后把暂停交给 EnterDesyncRecovery 由其请求新快照。由 UMassBattleSubsystem::Tick 的追帧块调用(:2020)。

[2026-08-29 FF-abort] Tears down an in-flight fast-forward and enters server-snapshot recovery instead of hard-chasing hundreds of ticks: when the FF falls more than FastForwardAbortBehindTicks behind the LIVE server head (e.g. the client hitched during catch-up), hard-chasing at FF rate takes minutes — abort and request a fresh server snapshot so the rebuild jumps straight to the server head and the fresh FF covers only a few ticks; especially important when the local FF rate trails the server advance (sustained hitch). Mirrors the FF-completion teardown (minus the completion broadcast and the FF-tick hash check), then hands the pause to EnterDesyncRecovery, which requests the fresh snapshot. Called from the fast-forward block of UMassBattleSubsystem::Tick (:2020).

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统。Main sim subsystem.
Output

无返回值。副作用:拆除追帧状态、转入硬失步恢复(暂停 + 事件广播)。

No return value. Side effects: tears down the FF state and enters hard desync recovery (pause + event broadcast).

EnterDesyncRecovery void

进入硬失步恢复(暂停模拟等待服务器快照):已在恢复中(bSimulationPaused && bHardDesyncDetected)时直接返回;否则置 bHardDesyncDetected、放弃本地路径意图(bPendingLocalRecovery = false,迟到指令直接触发的失步不经本地)、递增 RecoveryEpoch 认领暂停归属、置暂停,并广播 PauseForServerSnapshot 事件。由 UpdateNetworkClientPacing(严重落后)、UMassBattleSubsystem::Tick(客户端哈希失配)与 EvaluateDeferredDesyncChecks 调用。

Enters hard desync recovery (pause the sim waiting for a server snapshot): returns immediately when already in recovery (bSimulationPaused && bHardDesyncDetected); otherwise sets bHardDesyncDetected, abandons the local-path intent (bPendingLocalRecovery = false; late-command-triggered desyncs skip the local path), increments RecoveryEpoch to claim pause ownership, pauses, and broadcasts the PauseForServerSnapshot event. Called by UpdateNetworkClientPacing (severe lag), UMassBattleSubsystem::Tick (client hash mismatch) and EvaluateDeferredDesyncChecks.

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统(tick 计数用于事件)。Main sim subsystem (tick count for the event).
Output

无返回值。副作用:置恢复标志、递增 epoch、暂停模拟、广播事件。

No return value. Side effects: sets recovery flags, bumps the epoch, pauses the sim, broadcasts the event.

TriggerLocalResync bool

注入式手动触发本地快照 resync(无视自然失步检测;测试/调试用,如 BP 调试键或自动失步测试循环)。防重入——已有恢复在途(bPendingSnapshotApply/bSnapshotFastForward/bFastForwarding)时跳过并返回 false;失步暂停中(服务器恢复持有暂停)时跳过并提示改用 TriggerServerResync。随后直接调用 TryLocalSnapshotRecovery。经 UMassBattleFuncLib 暴露给 BP。

Injection-style manual trigger forcing a local-snapshot resync regardless of natural desync detection (testing/debugging, e.g. BP debug keys or the auto-desync test loop). Re-entrancy guard — skips and returns false when a recovery is already in flight (bPendingSnapshotApply/bSnapshotFastForward/bFastForwarding); skips with a hint to use TriggerServerResync while the desync pause is active (the server recovery owns the pause). Then calls TryLocalSnapshotRecovery directly. Exposed to BP via UMassBattleFuncLib.

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统(当前 tick 作为目标)。Main sim subsystem (current tick as the target).
Output

返回是否成功排队本地恢复(无可用已验证快照或重入 → false)。副作用:排队快照并置追帧意图;日志记录注入结果。

Returns whether local recovery was queued (no usable validated snapshot or re-entrancy → false). Side effects: queues the snapshot and sets the FF intent; logs the injection result.

TriggerServerResync void

注入式手动触发服务器快照 resync:无视当前状态强制进入硬失步恢复,刻意绕过 EnterDesyncRecovery 的重入保护(注入工具重复注入必须总是重新触发)。置标志、放弃本地路径、递增 epoch 认领暂停、记录首个请求 tick、广播暂停事件,当帧立即经 AMassBattleNetworkPlayerControllerBase::ServerRequestResync 发送请求(不等恢复分支的节流窗口);无 PC 时放行节流让恢复分支尽快重试。经 UMassBattleFuncLib 暴露给 BP。

Injection-style manual trigger forcing a server-snapshot resync: force-enters hard desync recovery regardless of current state, deliberately bypassing EnterDesyncRecovery's re-entrancy guard (a re-injection must always re-trigger, never no-op). Sets flags, abandons the local path, bumps the epoch to claim the pause, records the first request tick, broadcasts the pause event, and sends the request the same frame via AMassBattleNetworkPlayerControllerBase::ServerRequestResync (bypassing the recovery-branch throttle window); without a PC it releases the throttle so the recovery branch retries promptly. Exposed to BP via UMassBattleFuncLib.

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统(当前 tick 用于事件与请求)。Main sim subsystem (current tick for the event and request).
Output

无返回值。副作用:置恢复标志与暂停、递增 epoch、广播事件、发送 resync 请求 RPC。

No return value. Side effects: sets recovery flags and pause, bumps the epoch, broadcasts the event, sends the resync-request RPC.

客户端调速 Client Pacing

UpdateNetworkClientPacing void

客户端调速主入口(由 UMassBattleSubsystem::Tick 与 AMassBattleNetworkGameStateBase 调用):非网络模式/非客户端/ServerTickCount ≤ 0 时重置 delta 与比率并读 ping 后返回。否则按 ClientServerTickDelta = TickCount - ServerTickCount 分档:K = ceil(输入缓冲/每 tick 毫秒):① 追帧中 → 保持目标 ≥ 服务器 tick,比率 1;② 落后 ≥ 3K 且 ≥ LagResyncThresholdTicks(严重落后)→ 直接走服务器快照恢复(EnterDesyncRecovery),从陈旧本地状态纯 FF 几乎必然失步;冷却期内则暂停但不请求,冷却结束才进入硬失步;③ 落后但 < 3K(一般落后)→ 纯 FF(BeginFastForward(ServerTickCount)),无需快照;④ 落后 0..3K 之间 → 按比例加速到 MaxNetworkTickSpeedRatio;⑤ 领先 0..K → 强力减速 lerp 到 0.3;⑥ 领先 ≥ K → 比率 0(停摆);⑦ 对齐 → 1。仅在对齐或领先时乘以 ServerTimeDilation(落后的客户端保持完整追赶倍率)。MulticastSyncTick 是客户端 ServerTickCount 的唯一来源——缺失则调速完全失效。

Client pacing main entry (called by UMassBattleSubsystem::Tick and AMassBattleNetworkGameStateBase): on non-networked/non-client/ServerTickCount ≤ 0 it resets the delta and ratio, reads the ping, and returns. Otherwise it bands by ClientServerTickDelta = TickCount - ServerTickCount, with K = ceil(input-buffer ms / ms-per-tick): ① fast-forwarding → keeps the target ≥ server tick, ratio 1; ② behind ≥ 3K and ≥ LagResyncThresholdTicks (severe lag) → straight to server-snapshot recovery (EnterDesyncRecovery); pure FF from a stale local state almost certainly desyncs at every step; during the resync cooldown it pauses without requesting, entering hard desync only when the cooldown expires; ③ behind but < 3K (moderate lag) → pure FF (BeginFastForward(ServerTickCount)), no snapshot needed; ④ behind by 0..3K → accelerates by lerp up to MaxNetworkTickSpeedRatio; ⑤ ahead by 0..K → aggressive deceleration lerp to 0.3; ⑥ ahead ≥ K → ratio 0 (stall); ⑦ aligned → 1. ServerTimeDilation applies only when aligned or ahead (behind clients keep the full catch-up ratio). MulticastSyncTick is the only source of the client's ServerTickCount — without it pacing is dead.

Input
参数 Param类型 Type说明 Description
MBUMassBattleSubsystem*主模拟子系统(tick/步长/暂停状态)。Main sim subsystem (tick / step time / pause state).
Output

无返回值。副作用:更新 ClientServerTickDelta/CurrentTickSpeedRatio/NetworkLatencyMs(由消费方读取调节 tick 速度);严重落后时触发恢复/暂停与事件广播。

No return value. Side effects: updates ClientServerTickDelta/CurrentTickSpeedRatio/NetworkLatencyMs (consumed to scale the tick rate); severe lag triggers recovery/pause and event broadcasts.

快照模板注册表 Snapshot Template Registry

RegisterNetworkTemplateData FName (3 参数重载)

幂等注册快照模板:模板无效返回 NAME_None;确保 FNetworking.Key 存在(为空则自动生成 Template_N 并跳过已占 Key);Key 已注册则返回已有注册(幂等);否则无条件加 FNetworkTag(每个注册模板都参与锁步)后存入注册表并返回 Key。调用方:模板工厂(MakeAgentTemplateDataFromDataAsset / MakeLootTemplateFromDataAsset / MakeProjectileTemplateFromDataAsset)、骨架模板注册(Host/Debuff 子系统)与 UMassBattleFuncLib 的 BP 包装。

Idempotently registers a snapshot template: invalid templates return NAME_None; ensures FNetworking.Key exists (auto-generates Template_N when empty, skipping taken keys); an already-registered key returns the existing registration (idempotent); otherwise it unconditionally adds FNetworkTag (every registered template participates in lockstep), stores the template, and returns the key. Callers: the template factories (MakeAgentTemplateDataFromDataAsset / MakeLootTemplateFromDataAsset / MakeProjectileTemplateFromDataAsset), skeleton-template registrations (Host/Debuff subsystems) and the UMassBattleFuncLib BP wrapper.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文(透传)。World context (forwarded).
TemplateDataconst FEntityTemplateData&待注册模板;内部 FNetworking.Key 为空时会被写入自动 Key。Template to register; an empty inner FNetworking.Key gets an auto key.
OutRegisteredTemplateDataFEntityTemplateData&输出:实际注册的模板数据(幂等路径为已有条目)。Output: the actually-registered template data (the existing entry on the idempotent path).
Output

返回模板 Key(成功)或 NAME_None(模板无效)。副作用:写入 SnapshotTemplateRegistry、给模板加 FNetworkTag、可能写入自动 Key。

Returns the template key (success) or NAME_None (invalid template). Side effects: writes SnapshotTemplateRegistry, adds FNetworkTag to the template, possibly writes an auto key.

RegisterNetworkTemplateData FName (4 参数重载,UPARAM(ref))

带显式 Key 的重载(Blueprint 友好):Key 非空且模板有效时,把 Key 写入模板副本的 FNetworking.Key 后委托 3 参数版;否则直接委托 3 参数版(自动 Key 或幂等)。

Overload with an explicit key (Blueprint-friendly): when the key is non-empty and the template valid, it stamps the key into the template's FNetworking.Key and delegates to the 3-parameter version; otherwise it delegates directly (auto key or idempotent path).

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
TemplateDataconst FEntityTemplateData&待注册模板。Template to register.
OutRegisteredTemplateDataFEntityTemplateData&输出:实际注册的模板数据。Output: the actually-registered template data.
KeyFName显式模板 Key;为空时走自动 Key 路径。Explicit template key; empty falls back to the auto-key path.
Output

返回最终使用的模板 Key 或 NAME_None。副作用:同 3 参数版。

Returns the final template key or NAME_None. Side effects: same as the 3-parameter version.

GetNetworkTemplateData bool (const)

按 Key 查已注册模板(拷贝返回)。

Looks up a registered template by key (returned by copy).

Input
参数 Param类型 Type说明 Description
KeyFName模板 Key。Template key.
OutTemplateDataFEntityTemplateData&输出:查到的模板数据。Output: the found template data.
Output

返回是否命中;未命中返回 false 且 OutTemplateData 不保证有效。

Returns whether the key was found; false with OutTemplateData unspecified on a miss.

UnregisterSnapshotTemplateData void

从注册表移除指定 Key 的模板。

Removes the template for the given key from the registry.

Input
参数 Param类型 Type说明 Description
KeyFName模板 Key。Template key.
Output

无返回值。副作用:删除注册条目(不存在则无操作)。

No return value. Side effect: deletes the registry entry (no-op when absent).

流场基底缓存 Flow-Field Substrate Cache

服务器侧各流场名最后一次导出基底的缓存——晚加入补发源:客户端加入前广播的基底块不经 gap 命令到达加入者(快照只带块引用、不带字节),故 OnClientResyncComplete 从此处重播;导入幂等(内容哈希跳过)。刻意不复用 ReceivedLockstepDataBlocks——该表按重放窗口裁剪。

Server-side cache of the last-exported substrate per flow-field name — the late-join re-delivery source: substrate blocks broadcast BEFORE a client joins never reach the joiner via gap commands (snapshots carry only block references, never bytes), so OnClientResyncComplete re-broadcasts from here; the import is idempotent (content-hash skip). Deliberately NOT ReceivedLockstepDataBlocks — that map is pruned by the replay window.

CacheFlowFieldSubstrate void (inline)

把流场 FieldName 的最新导出基底字节写入 CachedFlowFieldSubstrates(同键覆盖)。由 AMassBattleNetworkGameModeBase 在导出/广播基底时调用(:1625/:1642,注释标明"晚加入补发源")。

Stores the latest exported substrate bytes of flow field FieldName into CachedFlowFieldSubstrates (same-key overwrite). Called by AMassBattleNetworkGameModeBase when exporting/broadcasting a substrate (:1625/:1642, marked "late-join re-delivery source").

Input
参数 Param类型 Type说明 Description
FieldNameFName流场名(缓存键)。Flow-field name (the cache key).
Dataconst TArray<uint8>&导出的基底字节。Exported substrate bytes.
Output

无返回值。副作用:写入/覆盖缓存条目。

No return value. Side effect: writes/overwrites the cache entry.

GetCachedFlowFieldSubstrates const TMap<FName, TArray<uint8>>& (inline, const)

只读访问全部已缓存基底。消费方:AMassBattleNetworkGameModeBase 的晚加入补发/重播路径(:1117/:1229/:1592/:1680-1686)与 AMassBattleNetworkGameStateBase 的 gap 命令基底回退查找(:563)。

Read-only access to all cached substrates. Consumers: the late-join re-delivery/replay paths of AMassBattleNetworkGameModeBase (:1117/:1229/:1592/:1680-1686) and the gap-command substrate fallback lookup in AMassBattleNetworkGameStateBase (:563).

Input

无参数。

No parameters.

Output

返回缓存 map 的常量引用。无副作用。

Returns a const reference to the cache map. No side effects.

查询与调试 Query & Debug

LogDesyncDetails void

失步诊断日志(仅 WITH_EDITOR 编译):打印 Agent 总数、TickCount、SimulationTime 与哈希网格前 20 个 agent 的位置/速度/质量,供双端日志 diff。经 UMassBattleFuncLib 暴露。

Desync diagnostic logging (compiled only under WITH_EDITOR): prints the agent count, TickCount, SimulationTime and the first 20 agents' position/velocity/mass from the hash grid for cross-peer log diffing. Exposed via UMassBattleFuncLib.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
TickCountint32诊断目标 tick。Diagnostic target tick.
Output

无返回值。副作用:输出日志;非编辑器构建或子系统缺失时静默返回。

No return value. Side effects: writes log output; silently returns in non-editor builds or when the subsystem is missing.

GetClientPing float

按 PlayerId 从 GameState 的 PlayerArray 查客户端延迟(毫秒)。

Looks up a client's latency in milliseconds by PlayerId from the GameState's PlayerArray.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
PlayerIndexint32玩家 PlayerId。Player's PlayerId.
Output

返回延迟毫秒数;未找到玩家或世界无效返回 -1.f。

Returns the latency in ms, or -1.f when the player or world is not found.

GetNetworkStats FMassBattleNetworkStats

组装网络统计:CommandQueueDepth(pending 指令数)、LastTickHash(TickHashHistory 中最大 tick 的哈希)、TotalDesyncs、LastSnapshotSizeBytes = 0(按需 resync,无定期快照)、bIsFastForwarding,并从 PlayerArray 收集各玩家 ping。经 UMassBattleFuncLib 暴露给 BP。

Assembles network stats: CommandQueueDepth (pending command count), LastTickHash (hash of the max tick in TickHashHistory), TotalDesyncs, LastSnapshotSizeBytes = 0 (on-demand resync — no periodic snapshot), bIsFastForwarding, plus per-player pings from the PlayerArray. Exposed to BP via UMassBattleFuncLib.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
Output

返回 FMassBattleNetworkStats(主模拟子系统缺失时返回默认值)。无副作用。

Returns FMassBattleNetworkStats (defaults when the main sim subsystem is missing). No side effects.

GetUniqueIDByEntity void

按实体句柄查 UID(MB->FindUIDByEntity 包装)。

Looks up the UID of an entity handle (wrapper over MB->FindUIDByEntity).

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
Handleconst FEntityHandle&实体句柄。Entity handle.
OutUniqueIDint32&输出:UID(初始化为 -1)。Output: UID (initialized to -1).
bFoundbool&输出:是否命中(UID ≥ 0)。Output: whether found (UID ≥ 0).
Output

无返回值。副作用:写两个输出参数。

No return value. Side effect: writes the two output parameters.

GetEntityByUniqueID void

按 UID 查实体句柄(MB->FindEntityByUID 包装);命中还需 IsValid 确认。

Looks up an entity handle by UID (wrapper over MB->FindEntityByUID); a hit additionally requires IsValid.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
UniqueIDint32实体 UID。Entity UID.
OutHandleFEntityHandle&输出:实体句柄(初始化为无效)。Output: entity handle (initialized invalid).
bFoundbool&输出:是否命中且有效。Output: whether found and valid.
Output

无返回值。副作用:写两个输出参数。

No return value. Side effect: writes the two output parameters.

IsPlayerJoined bool

判断玩家是否已完全加入:不在 late-join 队列、不在 resync 挂起集,且已绑定角色(FindPlayerCharacter 命中)。

Checks whether a player has fully joined: not in the late-join queue, not in the pending-resync set, and has a bound character (FindPlayerCharacter hit).

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
PlayerIdint32玩家 PlayerId。Player's PlayerId.
Output

返回是否已加入;主模拟子系统/世界/GameMode 缺失时返回 false。

Returns whether the player has joined; false when the main sim subsystem/world/GameMode is missing.

GetExecutionTick int32

计算"当前 tick + K"(K = ceil(服务器动态输入缓冲 / 每 tick 毫秒))——服务器为客户端指定命令的目标执行 tick。无 GameMode 时返回 0。

Computes "current tick + K" (K = ceil(server dynamic input buffer / ms per tick)) — the server-side target execute tick for client commands. Returns 0 without a GameMode.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
Output

返回目标执行 tick;主模拟子系统或 GameMode 缺失时返回 0。

Returns the target execute tick, or 0 when the main sim subsystem or GameMode is missing.

ResolveUniqueIDs TArray<FEntityHandle>

批量 UID → 句柄解析(逐项 LookupEntityByUniqueID)。不可解析的 ID 输出无效句柄占位,结果长度与输入对齐。

Batch UID → handle resolution (per-item LookupEntityByUniqueID). Unresolvable IDs become invalid-handle placeholders so the result stays length-aligned with the input.

Input
参数 Param类型 Type说明 Description
WorldContextconst UObject*世界上下文。World context.
UniqueIDsconst TArray<int32>&UID 列表。List of UIDs.
Output

返回与输入等长的句柄数组(不可解析项为无效句柄);空输入或子系统缺失返回空数组。

Returns a handle array of the input's length (unresolvable items are invalid handles); empty input or a missing subsystem returns an empty array.

UID 查找委派 UniqueID Lookup Delegation

LookupEntityByUniqueID FEntityHandle (const)

UID → 实体句柄,委派 UMassBattleSubsystem::FindEntityByUID;主模拟子系统缺失时返回无效句柄。

UID → entity handle, delegated to UMassBattleSubsystem::FindEntityByUID; returns an invalid handle when the main sim subsystem is missing.

Input
参数 Param类型 Type说明 Description
UniqueIDint32实体 UID。Entity UID.
Output

返回实体句柄(未注册返回无效句柄)。

Returns the entity handle (invalid when unregistered).

LookupUniqueIDByEntity int32 (const)

实体句柄 → UID,委派 UMassBattleSubsystem::FindUIDByEntity;主模拟子系统缺失时返回 -1。

Entity handle → UID, delegated to UMassBattleSubsystem::FindUIDByEntity; returns -1 when the main sim subsystem is missing.

Input
参数 Param类型 Type说明 Description
HandleFEntityHandle实体句柄。Entity handle.
Output

返回实体 UID;未注册或子系统缺失返回 -1。

Returns the entity UID, or -1 when unregistered or the subsystem is missing.

锁步宿主注册表 Lockstep Host Registry

RegisterLockstepHost void

把宿主(组件/actor)登记进 LockstepNetID → 宿主映射。由组件在 ID 分配(服务器)或 OnRep(客户端)时调用;ID ≥ 0 且宿主非空才写入。

Registers a host (component/actor) into the LockstepNetID → host map. Called by the component on ID assignment (server) or OnRep (client); only writes when the ID ≥ 0 and the host is non-null.

Input
参数 Param类型 Type说明 Description
LockstepNetIDint32服务器分配、UE 复制的宿主标识(非 entity UID)。Server-assigned, UE-replicated host identifier (not the entity UID).
HostUObject*绑定组件/actor(弱引用存储)。The bound component/actor (stored weakly).
Output

无返回值。副作用:写入 LockstepRegistry(弱引用)。

No return value. Side effect: writes LockstepRegistry (weak reference).

UnregisterLockstepHost void

从宿主映射移除 LockstepNetID(组件销毁路径)。ID ≥ 0 才移除。

Removes a LockstepNetID from the host map (component teardown path). Only removes when the ID ≥ 0.

Input
参数 Param类型 Type说明 Description
LockstepNetIDint32宿主标识。Host identifier.
Output

无返回值。副作用:删除映射条目(不存在则无操作)。

No return value. Side effect: deletes the map entry (no-op when absent).

FindLockstepHost UObject* (const)

按 LockstepNetID 找宿主:ID < 0 直接返回 nullptr;弱引用失效(对象已销毁)返回 nullptr。由指令执行分支(GameState::ExecuteNetCommand 定位 Agent/Projectile/Loot 组件)与 UMassBattleFuncLib 使用。

Finds a host by LockstepNetID: IDs < 0 return nullptr immediately; dead weak references (destroyed objects) return nullptr. Used by the command-execution branches (GameState::ExecuteNetCommand locating Agent/Projectile/Loot components) and UMassBattleFuncLib.

Input
参数 Param类型 Type说明 Description
LockstepNetIDint32宿主标识。Host identifier.
Output

返回宿主指针;未注册或已销毁返回 nullptr。

Returns the host pointer, or nullptr when unregistered or destroyed.

AllocNextLockstepNetID FORCEINLINE int32

服务器权威 LockstepNetID 分配器:FPlatformAtomics::InterlockedIncrement(&NextLockstepNetID)(从 -1 起,首次调用返回 0)。不碰实体 UID 分配(通用实体 UID 由 FEntityUIDAllocator 槽位分配器分配——2026-08-16 取代退役的 NextGlobalUID 计数器)。由 UMassBattleEntityComponentBase 在绑定初始化时调用。

Server-authoritative LockstepNetID allocator: FPlatformAtomics::InterlockedIncrement(&NextLockstepNetID) (starts at -1; the first call returns 0). Does not touch entity-UID allocation (general-entity UIDs come from the FEntityUIDAllocator slot allocator, which replaced the retired NextGlobalUID counter on 2026-08-16). Called by UMassBattleEntityComponentBase during binding initialization.

Input

无参数。

No parameters.

Output

返回下一个 LockstepNetID。副作用:原子自增计数器。

Returns the next LockstepNetID. Side effect: atomically increments the counter.

执行窗口守卫 Execution-window Guards

IsInCommandExecution / IsInSnapshotRestore FORCEINLINE bool (const)

读取两个执行窗口标志:bInCommandExecution 在 UMassBattleSubsystem::Tick 的锁步命令执行循环周围置位(DequeueNetCommandsForTick → ExecuteNetCommand → OnNetCommandExecuted);bSnapshotRestoreContext 在 ProcessDeferredSnapshot 的任务重建广播周围置位。均仅游戏线程、无原子。

Reads the two execution-window flags: bInCommandExecution is set around the lockstep command-execution loop in UMassBattleSubsystem::Tick (DequeueNetCommandsForTick → ExecuteNetCommand → OnNetCommandExecuted); bSnapshotRestoreContext is set around the task-restore broadcast in ProcessDeferredSnapshot. Both are game-thread-only, no atomics.

Input

无参数。

No parameters.

Output

分别返回是否处于命令执行窗口 / 快照恢复窗口。

Respectively returns whether in the command-execution window / the snapshot-restore window.

HandleFixup 注册 HandleFixup Appliers

RegisterHandleFixupApplier void (inline)

注册跨实体句柄修复处理器:HandleFixupAppliers.Add(FragmentTypeName, MoveTemp(Applier))。恢复端 ApplyEntitySnapshotPayload 解析 Payload.HandleFixups 时按 fragment 类型名委托。处理器签名为 TFunction<void(UMassBattleSubsystem&, FEntityHandle, FEntityHandle, const FEntityHandleFixup&)>(类型别名 FHandleFixupApplier)。

Registers a cross-entity handle-fixup applier: HandleFixupAppliers.Add(FragmentTypeName, MoveTemp(Applier)). When the restore side ApplyEntitySnapshotPayload resolves Payload.HandleFixups, it delegates by fragment type name. The applier signature is TFunction<void(UMassBattleSubsystem&, FEntityHandle, FEntityHandle, const FEntityHandleFixup&)> (type alias FHandleFixupApplier).

Input
参数 Param类型 Type说明 Description
FragmentTypeNameFNamefragment 类型名(委托键)。Fragment type name (delegation key).
ApplierFHandleFixupApplier修复处理器(移动语义)。The fixup applier (moved in).
Output

无返回值。副作用:写入 HandleFixupAppliers(同键覆盖)。

No return value. Side effect: writes HandleFixupAppliers (overwrites on a duplicate key).

TCP 快照传输 TCP Snapshot Transport

InitializeSnapshotTcpTransport void

按当前网络角色初始化 TCP 快照传输(幂等,可安全重复调用)。服务器(监听/专用):已活跃则跳过;存在但不活跃(上次启动失败)先拆除;生成会话令牌(RandRange(100000, 999999));显式端口冲突时回退 OS 分配,自动模式尝试 游戏端口+100..+109 再回退 OS 分配;绑定 OnLockstepDataBlockUploaded(上行块暂存 + 若有暂存命令立即汇聚)。客户端:已存在则跳过;绑定 OnSnapshotBytesReceived(反序列化失败向服务器报告 false,成功则 QueueSnapshotApply)与 OnLockstepDataBlockReceived(下行块缓存)。

Initializes the TCP snapshot transport for the current net role (idempotent, safe to call repeatedly). Server (listen/dedicated): skips when already active; tears down first when existing but inactive (a failed previous start); generates a session token (RandRange(100000, 999999)); falls back to an OS-assigned port on explicit-port conflict, and tries game-port +100..+109 in auto mode before the OS fallback; binds OnLockstepDataBlockUploaded (stages uplink blocks, converges a staged command immediately when one is waiting). Client: skips when it already exists; binds OnSnapshotBytesReceived (reports failure to the server on deserialization errors, otherwise QueueSnapshotApply) and OnLockstepDataBlockReceived (caches downlink blocks).

Input

无参数(使用成员配置 SnapshotTcpPort / SnapshotTcpBindAddress 与世界的 NetMode/端口)。

No parameters (uses the member config SnapshotTcpPort / SnapshotTcpBindAddress and the world's NetMode/port).

Output

无返回值。副作用:创建/重建 SnapshotTcpTransport、分配令牌、绑定回调;启动失败打 Error 日志。由 Initialize 调用,也由 EnsureSnapshotTcpTransport 重试。

No return value. Side effects: creates/rebuilds SnapshotTcpTransport, allocates the token, binds callbacks; logs an Error on startup failure. Called from Initialize and retried by EnsureSnapshotTcpTransport.

EnsureSnapshotTcpTransport bool

确保 TCP 传输存在且对当前网络模式活跃:客户端缺失则重试初始化;服务器缺失或不活跃则重试初始化;单机模式(尚未成为服务器/客户端)推迟并返回 false。由 AMassBattleNetworkPlayerControllerBase 与 AMassBattleNetworkGameModeBase 在发送快照/块前调用。

Ensures the TCP transport exists and is active for the current net mode: the client retries init when missing; the server retries when missing or inactive; standalone (not yet a server or client) defers and returns false. Called by AMassBattleNetworkPlayerControllerBase and AMassBattleNetworkGameModeBase before sending snapshots/blocks.

Input

无参数。

No parameters.

Output

返回传输是否就绪(客户端:非空;服务器:存在且活跃;单机:false)。副作用:可能触发初始化。

Returns whether the transport is ready (client: non-null; server: exists and active; standalone: false). Side effect: may trigger initialization.

TickSnapshotTcpTransport void

推进 TCP 传输(套接字收发包)并调用 PruneStaleBlocks() 清理超龄块。由 UMassBattleSubsystem::Tick 每逻辑帧调用。

Advances the TCP transport (socket send/receive) and calls PruneStaleBlocks() to drop aged-out blocks. Called every logic frame by UMassBattleSubsystem::Tick.

Input

无参数。

No parameters.

Output

无返回值。副作用:传输收发、块清理。

No return value. Side effects: transport I/O, block pruning.

ShutdownSnapshotTcpTransport void

关闭并释放 TCP 传输对象(置空指针)。

Shuts down and frees the TCP transport object (nulls the pointer).

Input

无参数。

No parameters.

Output

无返回值。副作用:传输关闭、删除、置空。

No return value. Side effects: transport shut down, deleted, nulled.

GetSnapshotTcpTransport FMassBattleSnapshotTcpTransport* (inline)

返回传输实例原始指针(供 GameMode/PlayerController 发送/接收);未初始化时为 nullptr。

Returns the raw transport instance pointer (for GameMode/PlayerController send/receive); nullptr when uninitialized.

Input

无参数。

No parameters.

Output

返回传输指针或 nullptr。

Returns the transport pointer or nullptr.

玩家角色查找 Player Character Lookup

FindPlayerCharacter ACharacter* (const)

按 PlayerId 查找玩家 ACharacter(possess 链推导,无中心映射):先查本地 PC 的 Pawn(PlayerState 匹配),再遍历世界全部 Character 的 PlayerState;PlayerId < 0 或世界缺失返回 nullptr。

Finds a player's ACharacter by PlayerId (possess-chain derived, no central map): first checks the local PC's pawn (PlayerState match), then iterates all Characters in the world by PlayerState; returns nullptr for PlayerId < 0 or a missing world.

Input
参数 Param类型 Type说明 Description
PlayerIdint32玩家 PlayerId。Player's PlayerId.
Output

返回角色指针;未找到或参数无效返回 nullptr。

Returns the character pointer, or nullptr when not found or the input is invalid.

成员变量 Members

指令队列 Command Queue

名称 Name类型 Type默认值说明 Description
PendingNetCommandsTArray<FMassBattleNetCommand>—已入队待执行的指令(确定性有序)。Enqueued, not-yet-executed commands (deterministically ordered).
ReceivedCommandsTArray<FMassBattleNetCommand>—已接收指令历史(本地恢复 gap 填充与晚加入使用;随 dequeue 裁剪)。Received-command history (local-recovery gap fill and late-join; pruned with dequeue).
ExecutedCommandKeyToTickTMap<uint64, int32>—已执行命令的 key → 执行 tick 账本(去重依据)。Executed command key → tick ledger (dedup basis).
ExecutedCommandPruneTickint320上次账本裁剪 tick(每 1024 tick 一次)。Last ledger-prune tick (every 1024 ticks).

lockstep 数据块 Data Blocks

名称 Name类型 Type默认值说明 Description
ReceivedLockstepDataBlocksTMap<int32, FReceivedLockstepDataBlock>—已接收(下行或汇聚)块,按权威 BlockId 索引;引用命令触发时消费。Received (downlink or converged) blocks keyed by authoritative BlockId; consumed when the reference command fires.
UploadedLockstepDataBlocksTMap<int32, TMap<int32, FReceivedLockstepDataBlock>>—仅服务器:客户端上行块暂存,键 [PlayerSlot][LocalBlockId]。Server-only: client uplink blocks staged by [PlayerSlot][LocalBlockId].
PendingBlockCommandsTMap<int32, TMap<int32, FPendingBlockCommand>>—仅服务器:TCP 块未到达的上行引用命令暂存(竞态修复)。Server-only: staged uplink reference commands whose TCP block has not arrived (race fix).
NextServerBlockIdint321权威 BlockId 分配器(服务器)。Authoritative BlockId allocator (server).
NextLocalBlockIdint321本地 BlockId 分配器(客户端上行)。Local-only BlockId allocator (client uplink).
StagedBlockCommandsTArray<FStagedBlockCommand>—【修复 2026-08-29】客户端"块未到"暂存等待列表(嵌套结构 = 命令 + 暂存墙钟);FlushStagedBlockCommands 冲刷,非空期间本地时间线冻结。[FIX 2026-08-29] Client-side block-not-yet-arrived staging list (nested struct = command + staging wall-clock); flushed by FlushStagedBlockCommands, local timeline frozen while non-empty.
StagedSpawnCommandsTArray<FStagedSpawnCommand>—【修复 2026-09-07】客户端"宿主组件未复制"生成命令暂存等待列表(同款结构);FlushStagedSpawnCommands 冲刷。[FIX 2026-09-07] Client-side host-component-not-replicated spawn staging list (same struct shape); flushed by FlushStagedSpawnCommands.

哈希与快照 Hash + Snapshot

名称 Name类型 Type默认值说明 Description
LastTickHashint640本 tick 全局哈希,由 MassBattleNetworkProcessor 折叠写入;OnTickCompleted 广播与快照 ServerHashAtCapture 读取。Per-tick global hash folded by MassBattleNetworkProcessor; read by the OnTickCompleted broadcast and snapshot ServerHashAtCapture.
SnapshotIntervalTicksint32 (UPROPERTY)90周期性快照间隔(每 N tick 采集一次);≤ 0 关闭周期采集。Periodic snapshot interval (capture every N ticks); ≤ 0 disables periodic capture.
NetworkFlushIntervalTicksint32 (UPROPERTY)1网络 flush 节拍——命令广播/哈希广播/快照采集每 N tick 一次;1 = 旧行为每 tick;按 tick 序号而非墙钟。Network flush cadence — command broadcast/hash broadcast/latest-snapshot capture every N ticks; 1 = legacy per-tick behavior; tick-indexed, never wall-clock.
bEnableFxHashbool (UPROPERTY)true是否把 FxHost/FxEntity 折进 per-tick EntityHash(调试确定性用);所有端必须一致,否则恢复哈希校验不对称。Whether FxHost/FxEntity fold into the per-tick EntityHash (debug-determinism aid); all peers must read the same value or restore hash validation becomes asymmetric.
bAuditUIDRegistrationbool (UPROPERTY)falseUID 注册审计开关:生成点现已构建即注册(BuildEntityDeferRegistered,引擎固定命令类型序 Create < Set 保证"查询可见 ⇔ 已注册");此开关门控的 NetworkProcessor pass 只检测、不治愈未注册实体([UID_REG_MISS],fail loud)。默认关闭以回收每 tick 遍历成本——排查生成点注册问题时临时置 true。UID-registration audit toggle: spawn sites now register at build time (BuildEntityDeferRegistered; the engine's fixed command-type order Create < Set guarantees "query-visible ⇔ registered"); the NetworkProcessor pass this gates DETECTS but never heals unregistered entities ([UID_REG_MISS], fail loud). Off by default to reclaim the per-tick traversal cost — flip true temporarily while debugging a spawn site.
bDisableFieldRegistrationAuditbool (UPROPERTY, Config)false字段注册审计退出开关:该审计是静默锁步失步的编辑器看门狗——报告 (a) 网络实体上整片段缺失(不在快照+hash 注册表、亦未豁免)与 (b) 未注册 UPROPERTY 字段的运行时变化(影子值比较,每片段/字段每会话只报一次);报错指引点名要改的注册表宏(MassBattleSnapshotRegistry.h)或豁免清单。仅诊断、不写片段、不影响锁步;编辑器构建默认运行(调用点 #if WITH_EDITOR),打包构建整体编译剔除。分拣完成后置 true 退出。可在 DefaultMassBattle.ini 开关。Field-registration audit opt-out: the audit is an editor watchdog for silent lockstep divergence — it reports (a) whole fragments present on networked entities but absent from the snapshot+hash registries and the exclusion list, and (b) runtime CHANGES of unregistered UPROPERTY fields (shadow value compare, one report per fragment/field per session); the report names the exact registry macro to edit (MassBattleSnapshotRegistry.h) or the exclusion list. Diagnostics only — no fragment writes, no lockstep impact; editor builds run it by default (#if WITH_EDITOR-gated call site), packaged builds compile it out entirely. Flip true when the triage is done. Config-switchable in DefaultMassBattle.ini.
FieldAuditIntervalTicksint32 (UPROPERTY, Config, ClampMin 1)32审计节奏(逻辑 tick;60fps 步进下约每半秒一次)。Audit cadence in logic ticks (32 ≈ once per half second at 60 fps stepped).
FieldAuditShadow / FieldAuditShadowUID / FieldAuditReportedTMap<FString,FString> / TMap<FString,int32> / TSet<FString>—审计会话状态:影子值("Frag.Field" → 导出值)、影子来源实体 UID(同 UID 门控抑制代表实体漂移造成的幻影"变更")与已上报去重集。Audit session state: shadow values ("Frag.Field" → exported value), the source entity UID per shadow (the same-UID gate suppresses phantom "changes" from representative flapping), and the reported-dedup set.
bForceSnapshotNextTickboolfalse下一 tick 强制快照。Force a snapshot on the next tick.
ForceSnapshotEveryTickRemainingint320剩余逐 tick 强制快照计数。Remaining every-tick force-snapshot count.
EntitySnapshotBufferFParallelGatherer<FEntitySnapshotRecord>—agent 快照记录并行收集器(并行安全);CacheLatestSnapshot 合并排序。Parallel gatherer for agent snapshot records; merged/sorted by CacheLatestSnapshot.
NetworkHashEntriesFParallelGatherer<FEntityNetworkEntry>—每 tick 哈希条目收集器。必须为成员(非栈上局部)——TLS 指针缓存会碰撞已释放槽位。Per-tick hash-entry gatherer. MUST be a member (not stack-local) — the TLS pointer cache would collide with a freed slot.
DiagAgentCompGatherer / DiagProjectileCompGathererFParallelGatherer<FPerEntityHashTick::FDiagAgentComp> / <FDiagProjectileComp>—[DIAG] 逐 agent / 逐 projectile 分量哈希的并行安全收集器,喂给逐 tick 历史(受 bEnablePerEntityHashDiag 总闸)。[DIAG] Parallel-safe collectors for per-agent / per-projectile component hashes, feeding the per-tick history (gated by the bEnablePerEntityHashDiag master switch).
PerEntityHashHistoryTArray<FPerEntityHashTick>—逐 tick 逐实体 hash 历史(环形)——FF 后失步诊断:定位最先失步实体。Per-tick per-entity hash history (ring) — post-FF desync diagnosis: identifies the first diverging entity.
bEnablePerEntityHashDiagbool (UPROPERTY, Config)true (TEMP-DIAG)逐实体 hash DIAG 链总闸:逐 fragment 分量哈希(agent 每实体每 tick 6 次 / 弹体约 10 次 MixHashFragmentInto)、PerEntityHashHistory 记录(128-tick 环形)与失步 [DIVERGE_TICK]/[CLI_*] 转储。设计默认关闭 = 每 tick 零开销;当前源码临时置 true(Config)排查 resync 循环,排查后双端翻回。Master gate for the per-entity hash DIAG chain: per-fragment component hashing (agent ×6 / projectile ×~10 MixHashFragmentInto per entity per tick — the hot-path cost), PerEntityHashHistory recording (128-tick ring), and the desync [DIVERGE_TICK]/[CLI_*] dumps. Designed default off = zero per-tick overhead; the source currently flips it to true (Config) as a TEMP-DIAG for the resync-loop hunt, to be flipped back on both peers afterwards.
bLogPerEntityHashesbool (UPROPERTY, Config)false调试:双端每 tick 打印逐实体 hash([HASH_ENT] 对照 [DIVERGE_TICK] 定位失步实体);同时门控逐 tick [HASH_TICK] 校验行(定位首个分歧 tick)。默认关闭(每轮日志可达数百 MB);排查失步时再开启。Debug: logs per-entity hashes each tick on both peers (diff [HASH_ENT] vs [DIVERGE_TICK] to find the diverging entity); also gates the per-tick [HASH_TICK] validation line (first diverging tick). Off by default (per-run logs can reach hundreds of MB); enable while hunting desyncs.
CachedLatestSnapshotTSharedPtr<FEntitySnapshotPayload, ESPMode::ThreadSafe>—确定性快照缓存(最新)——共享不可变载荷:验证环持有同一对象(指针共享,零拷贝,旧的逐槽深拷贝是 17.5 万次 blob 分配);两个持有者只整体换指针、从不原地改,消费端(GameMode 发送/本地恢复)变更前均已拷贝。Deterministic snapshot cache (latest) — a SHARED immutable payload: the validated ring holds the same object by pointer (zero copy; the old per-slot deep copy was 175k blob allocations); both holders only ever swap the pointer and never mutate in place; consumers (GameMode send / local recovery) copy before mutating.
PendingVarStoreSnapshotTArray<FVarStoreSnapshotEntry> (UPROPERTY)—LockstepVarStore 采集缓冲——网络处理器在折叠点填充,CacheLatestSnapshot 移入缓存。LockstepVarStore capture buffer — filled by the network processor at the fold point, moved into the cache by CacheLatestSnapshot.
SnapshotLayoutCacheTMap<FName, FSnapshotFragmentLayout>—快照布局缓存(注册表驱动,惰性构建)。Snapshot layout cache (registry-driven, lazily built).
HashLayoutCacheTMap<FName, FHashFragmentLayout>—哈希布局缓存(镜像快照布局,纯 C++ 无 UHT)。Hash layout cache (mirrors the snapshot layout; plain C++, no UHT).
ValidatedSnapshotsTArray<FValidatedSnapshot>—已验证快照环缓冲(MaxRecentSnapshots = 8);槽 0 永不覆盖。Validated-snapshot ring buffer (MaxRecentSnapshots = 8); slot 0 is never overwritten.
RecentSnapshotWriteIdxint320环缓冲写入游标。Ring-buffer write cursor.
LagResyncThresholdTicksint32 (UPROPERTY)300落后 tick 阈值——超过则直接走服务端快照恢复,不试本地快照。Lag threshold in ticks — beyond it, recovery goes straight to a server snapshot without trying the local one.
bPendingSnapshotApplyboolfalse有待应用快照标志。Pending snapshot apply flag.
PendingSnapshotPayloadFEntitySnapshotPayload—排队中的快照载荷。The queued snapshot payload.
PendingSnapshotTargetTickint32-1应用后的追帧目标 tick(-1 = 不追帧)。Fast-forward target after apply (-1 = none).
LastAppliedSnapshotPayloadTickint32-1上次成功应用 payload 的 tick(过期快照拒绝依据)。Tick of the last successfully applied payload (stale-snapshot rejection basis).

哈希历史 Hash History

名称 Name类型 Type默认值说明 Description
TickHashHistoryTMap<int32, int64>—本端逐 tick 哈希历史(由 UMassBattleSubsystem::Tick 写入并裁剪)。This peer's per-tick hash history (written and trimmed by UMassBattleSubsystem::Tick).
ServerHashHistoryTMap<int32, int64>—服务器逐 tick 哈希历史(由 AMassBattleNetworkGameStateBase 写入)。Server per-tick hash history (written by AMassBattleNetworkGameStateBase).
HashHistoryLengthint32 (UPROPERTY)256本端哈希历史保留长度(tick)。Local hash-history retention length (ticks).

快进与失步 Fast-Forward & Desync

名称 Name类型 Type默认值说明 Description
bFastForwardingbool (UPROPERTY, BlueprintReadOnly)false正在追帧。Fast-forward in progress.
FastForwardAbortBehindTicksint32 (UPROPERTY, Config)600【追帧中止】追帧落后服务器活前沿超过该 tick 数时中止硬追、改为请求新服务器快照(重建直接跳到服务器前沿附近);本机 FF 速率低于服务器推进速率(持续卡顿)时尤为重要。[FF-abort] When a fast-forward falls more than this many ticks behind the LIVE server head, abort the hard chase and request a fresh server snapshot instead (the rebuild jumps straight to the server head); especially important when the local FF rate trails the server advance (sustained hitch).
FastForwardStartTickint320追帧起始 tick。Fast-forward start tick.
FastForwardTargetTickint320追帧目标 tick。Fast-forward target tick.
bSnapshotFastForwardboolfalse快照恢复后的追帧(与纯追帧区分)。FF after snapshot recovery (as opposed to pure catch-up FF).
FastForwardMismatchCountint32 (UPROPERTY, BlueprintReadOnly)0追帧期间的哈希失配累计。Accumulated hash mismatches during FF.
FastForwardMismatchTickint32 (UPROPERTY, BlueprintReadOnly)0首次失配 tick。First-mismatch tick.
bResyncValidationSuppressedboolfalseresync 后哈希校验抑制标志(恢复后短窗内跳过校验)。Resync hash-validation suppression flag (validation skipped briefly after restore).
ResyncValidationResumeTickint320校验恢复 tick。Validation-resume tick.
DesyncConfirmTicksint32 (UPROPERTY, ClampMin 1, ClampMax 64)5【修复 2026-09-07·失步防抖】哈希失配升级为 RecordDesync+恢复(客户端)/DESYNC+隔离(服务器)所需的连续失配 flush tick 数——瞬态(自愈型)1-2 tick 毛刺到不了阈值,真发散仅延后 N tick 被发现。保留为保险层而非承重结构(两类历史病根已根治);纪律:本去抖不是"毛刺可容忍"的许可——今后任何连击/短失配都是新根因的第一个样本,必须排查,不许靠本层吸收。[FIX 2026-09-07 desync-debounce] Consecutive mismatching flush ticks required before a hash mismatch escalates to RecordDesync+recovery (client) / DESYNC+quarantine (server) — a 1-2 tick transient (self-healing) blip never reaches the threshold, and a real divergence is merely detected N ticks later. Retained as insurance, not load-bearing (both historical blip sources are eradicated); discipline: this debounce is NOT a license to tolerate blips — any future streak/short mismatch is the FIRST SAMPLE of a new root cause and must be investigated, never absorbed.
ConsecutiveDesyncMismatchTicksint320客户端校验侧连击计数(服务器在 GameMode 自持每玩家 map):每个失配校验 tick 递增,任一匹配校验 tick 清零。Client-side evaluation streak counter (the server keeps its own per-player map in the GameMode): incremented per mismatching validated tick, reset by any matching validated tick.
LastDesyncTickint32 (UPROPERTY, BlueprintReadOnly)0最近一次失步 tick。Tick of the most recent desync.
TotalDesyncCountint32 (UPROPERTY, BlueprintReadOnly)0失步总次数。Total desync count.
bSimulationPausedboolfalse模拟暂停(恢复流程持有)。Simulation paused (held by the recovery flow).
bHardDesyncDetectedboolfalse硬失步已检测(恢复中)。Hard desync detected (recovery in progress).
RecoveryEpochint320暂停归属 epoch——恢复的 FF 完成只能解除自己拥有的暂停。Pause-ownership epoch — a recovery's FF completion may only clear the pause it owns.
FFPauseEpochint32-1当前暂停所属 epoch(-1 = 无)。Epoch owning the current pause (-1 = none).
ResyncGenerationint320每次成功应用快照递增——混入渲染身份令牌,GPU resync 后跳变插值。Incremented on every successful snapshot apply — baked into render identity tokens so the GPU snaps interpolation after resync.
LastResyncRequestServerTickint32-120上次 resync 请求的服务器 tick(节流依据)。Server tick of the last resync request (throttle basis).
bPauseWaitServerActiveboolfalse暂停等待服务器状态标志。Pause-waiting-for-server state flag.
ResyncRequestCooldownTicksint32 (UPROPERTY)120resync 请求冷却(tick)。Resync request cooldown (ticks).
ResyncRequestTimeoutTicksint32600resync 请求超时(tick)。Resync request timeout (ticks).
FirstResyncRequestTickint32-1首个 resync 请求 tick(超时追踪)。First resync request tick (timeout tracking).
LastResyncCompletedTickint32-999上次 resync 完成 tick。Last resync completion tick.
PostResyncCooldownTicksint32300resync 后冷却(tick)。Post-resync cooldown (ticks).
bLastRecoveryWasLocalboolfalse最近一次恢复走本地快照路径(true)或服务端(false);EvaluateDeferredDesyncChecks 据此在本地恢复立刻失配时跳过 PostResyncCooldown。Whether the last recovery used the local-snapshot path (true) or the server one (false); EvaluateDeferredDesyncChecks uses it to skip PostResyncCooldown when a local recovery immediately re-mismatches.
bPendingLocalRecoveryboolfalse瞬态意图:本地恢复排队前置 true,ProcessDeferredSnapshot 消费(写入 bLastRecoveryWasLocal)后清零。Transient intent: set true before TryLocalSnapshotRecovery queues; consumed by ProcessDeferredSnapshot (writes bLastRecoveryWasLocal) then cleared.

客户端调速 Client Pacing

名称 Name类型 Type默认值说明 Description
ServerTickCountint320服务器 tick(经 MulticastSyncTick 更新)。Server tick (updated via MulticastSyncTick).
ClientServerTickDeltaint32 (UPROPERTY, BlueprintReadOnly)0客户端相对服务器 tick 偏移。Client tick offset relative to the server.
CurrentTickSpeedRatiofloat (UPROPERTY, BlueprintReadOnly)1.0f当前 tick 速度比率(0 = 停摆,1 = 正常,>1 加速追赶)。Current tick-speed ratio (0 = stalled, 1 = normal, >1 = catch-up).
MinNetworkTickSpeedRatiofloat (UPROPERTY)0.75f调速下限(当前实现未用于比率下限计算)。Pacing lower bound (not used by the current ratio math).
MaxNetworkTickSpeedRatiofloat (UPROPERTY)1.25f调速上限(落后时 lerp 的目标)。Pacing upper bound (lerp target when behind).
LastKnownInputBufferMsfloat (UPROPERTY, BlueprintReadOnly)150.0f服务器最近报告的输入缓冲(毫秒);K 缓冲计算的输入。Latest server-reported input buffer (ms); input to the K-buffer math.
ServerTimeDilationfloat1.0f服务器时间膨胀;仅对齐/领先时乘入比率。Server time dilation; multiplied into the ratio only when aligned/ahead.
NetworkLatencyMsfloat (UPROPERTY, BlueprintReadOnly)0.0f客户端网络延迟(毫秒,读 PlayerState ping)。Client network latency (ms, read from PlayerState ping).

注册表与守卫 Registry & Guards

名称 Name类型 Type默认值说明 Description
SnapshotTemplateRegistryTMap<FName, FEntityTemplateData>—快照模板注册表(Key → 模板)。Snapshot template registry (Key → template).
CachedFlowFieldSubstratesTMap<FName, TArray<uint8>>—服务器侧各流场末次导出基底缓存——晚加入补发源(刻意不复用按重放窗口裁剪的 ReceivedLockstepDataBlocks);GameMode 导出时写入,晚加入/gap 回退路径读取。Server-side cache of the last-exported substrate per flow-field name — the late-join re-delivery source (deliberately not ReceivedLockstepDataBlocks, which is pruned by the replay window); written by the GameMode at export, read by the late-join/gap fallback paths.
LockstepRegistryTMap<int32, TWeakObjectPtr<UObject>>—LockstepNetID → 宿主映射(弱引用;agent/projectile/loot 共享 ID 空间 → 单注册表)。LockstepNetID → host map (weak; shared ID space across agent/projectile/loot → single registry).
NextLockstepNetIDvolatile int32-1服务器权威 LockstepNetID 计数器(原子自增;不碰实体 UID 分配器 FEntityUIDAllocator)。Server-authoritative LockstepNetID counter (atomic increment; does not touch the FEntityUIDAllocator entity-UID allocator).
bInCommandExecutionboolfalse锁步命令执行窗口标志(游戏线程,无原子)。Lockstep command-execution window flag (game-thread only, no atomics).
bSnapshotRestoreContextboolfalseresync 任务重建窗口标志(任务工厂可在此创建任务)。Resync task-restore window flag (task factories may create tasks here).
HandleFixupAppliersTMap<FName, FHandleFixupApplier>—跨实体句柄修复处理器注册表(按 fragment 类型名)。Cross-entity handle-fixup applier registry (by fragment type name).

网络委托 Network Delegates

名称 Name类型 Type说明 Description
OnTickCompletedFOnTickCompleted (UPROPERTY, BlueprintAssignable)每逻辑 tick 末触发(参数:TickCount, TickHash);GameMode/GameState 绑定做中继。Fires at the end of each logic tick (params: TickCount, TickHash); GameMode/GameState bind it for relay duties.
OnNetCommandExecutedFOnNetCommandExecuted每条网络指令执行时触发(参数:Cmd)。Fires on every net command execution (param: Cmd).
OnNetworkEventFOnMassBattleNetworkEvent (UPROPERTY, BlueprintAssignable)统一网络事件——失步/暂停/快进通知(参数:EventData,见枚举表发射点)。Unified network event — desync/pause/fast-forward notifications (param: EventData; emit sites in the enum table).

TCP 配置 TCP Config

名称 Name类型 Type默认值说明 Description
SnapshotTcpPortint32 (UPROPERTY, Config)0TCP 快照服务器端口;0 = 自动(游戏端口 + 100 起)。TCP snapshot server port; 0 = auto (game port + 100 onward).
SnapshotTcpBindAddressFString (UPROPERTY, Config)TEXT("127.0.0.1")TCP 快照服务器绑定地址;默认仅本机(PIE/ListenServer 安全),DedicatedServer 设 0.0.0.0 接受远程。TCP snapshot server bind address; default localhost-only (safe for PIE/ListenServer); DedicatedServer sets 0.0.0.0 to accept remote clients.
SnapshotTcpTokenint320TCP 认证会话令牌——服务器随机生成,经 RPC 发送。TCP auth session token — randomly generated on the server, sent via RPC.
SnapshotTcpTransportFMassBattleSnapshotTcpTransport* (private)nullptr私有传输实例(裸指针,生命周期由本子系统管理)。Private transport instance (raw pointer, lifetime managed by this subsystem).

管线角色 Pipeline Role

在 MassBattle 管线中的位置(全部经 grep 验证):上游调用者——① UMassBattleSubsystem::Tick 每逻辑帧驱动:DequeueNetCommandsForTick(零容忍迟到判定,1.19.20 移除容忍路径)→ GameState::ExecuteNetCommand → OnNetCommandExecuted.Broadcast(窗口内置 bInCommandExecution);暂存等待检查 FlushStagedBlockCommands|FlushStagedSpawnCommands(:1401,返回真则冻结本地时间线,未执行后继命令经 RequeueCommandsFront 插回队头 :1457/:1832);EnterDesyncRecovery/RecordDesync(哈希失配)、AbortFastForwardForSnapshot(追帧落后超限,:2020)、UpdateNetworkClientPacing、ProcessDeferredSnapshot(帧末)、CacheLatestSnapshot(OnTickCompleted 广播前;被替换记录经 RetireSnapshotEntitiesAsync 后台退休)、TickSnapshotTcpTransport、OnTickCompleted.Broadcast(TickCount, LastTickHash);② MassBattleNetworkProcessor 每 tick 折叠 LastTickHash(预填 PreBuildSnapshotLayoutCache/PreBuildHashLayoutCache,采集 NetworkHashEntries 与 PendingVarStoreSnapshot,bCaptureSnapshot 采集点;并运行 UID 注册审计(bAuditUIDRegistration 门控)与字段注册审计(bDisableFieldRegistrationAudit / FieldAuditIntervalTicks 节流));③ AMassBattleNetworkGameStateBase 写入 ServerHashHistory、调 ValidateSnapshotsAgainstServerHash/SetServerSyncState/UpdateNetworkClientPacing,其 EvaluateDeferredDesyncChecks 按 DesyncConfirmTicks 连击防抖后触发 EnterDesyncRecovery/TryLocalSnapshotRecovery,块/宿主未到的下行命令走 StageBlockWaitCommand/StageSpawnWaitCommand;④ AMassBattleNetworkGameModeBase 绑定 OnTickCompleted、ConvergeUplinkBlock(块/命令汇聚)、EnsureSnapshotTcpTransport,客户端命令闸门拒绝时广播 CommandRejectedByWhitelist,流场导出走 CacheFlowFieldSubstrate;⑤ AMassBattleNetworkPlayerControllerBase 客户端输入 EnqueueNetCommand、监听服务器主机上行走 StageLocalUplinkBlock、BeginFastForward;⑥ UMassBattleEntityComponentBase 分配/注册/注销 LockstepNetID。 下游驱动——本子系统驱动:模板工厂注册(AgentSubsystem/LootSubsystem/ProjectileSubsystem/HostSubsystem 骨架与 DA 模板)、ProcessDeferredSnapshot 中的组件 RebindToEntity 与 AgentSubsystem::RebindLocalVisualsAfterResync 与 BP 任务重建、ApplyEntitySnapshotPayload 中的 HostSubsystem 池回填/音频并发重建/宿主刷新与 HashGrid::ResetOccupiedAgentCells;resync 请求经 NetPC::ServerRequestResync 上行,快照经 TCP 回调 QueueSnapshotApply 下行。

Position in the MassBattle pipeline (all grep-verified): upstream callers — ① UMassBattleSubsystem::Tick drives it every logic frame: DequeueNetCommandsForTick (zero-tolerance late judgment; the tolerate-late path was removed in 1.19.20) → GameState::ExecuteNetCommand → OnNetCommandExecuted.Broadcast (with bInCommandExecution set around the window); the staged-wait check FlushStagedBlockCommands|FlushStagedSpawnCommands (:1401 — a true return freezes the local timeline, un-executed successors re-queued at the head via RequeueCommandsFront :1457/:1832); EnterDesyncRecovery/RecordDesync (hash mismatch), AbortFastForwardForSnapshot (FF fallen too far behind, :2020), UpdateNetworkClientPacing, ProcessDeferredSnapshot (end of frame), CacheLatestSnapshot (before the OnTickCompleted broadcast; replaced records retired in the background via RetireSnapshotEntitiesAsync), TickSnapshotTcpTransport, and OnTickCompleted.Broadcast(TickCount, LastTickHash); ② MassBattleNetworkProcessor folds LastTickHash each tick (pre-fills PreBuildSnapshotLayoutCache/PreBuildHashLayoutCache, gathers NetworkHashEntries and PendingVarStoreSnapshot at the bCaptureSnapshot point; also runs the UID-registration audit, gated by bAuditUIDRegistration, and the field-registration audit, throttled by bDisableFieldRegistrationAudit / FieldAuditIntervalTicks); ③ AMassBattleNetworkGameStateBase writes ServerHashHistory, calls ValidateSnapshotsAgainstServerHash/SetServerSyncState/UpdateNetworkClientPacing, and its EvaluateDeferredDesyncChecks escalates only after the DesyncConfirmTicks debounce streak, then triggers EnterDesyncRecovery/TryLocalSnapshotRecovery; downlink commands whose block/host has not arrived go through StageBlockWaitCommand/StageSpawnWaitCommand; ④ AMassBattleNetworkGameModeBase binds OnTickCompleted, converges uplink blocks (ConvergeUplinkBlock), ensures the TCP transport, broadcasts CommandRejectedByWhitelist from the client-command gate, and feeds flow-field exports into CacheFlowFieldSubstrate; ⑤ AMassBattleNetworkPlayerControllerBase enqueues client input (EnqueueNetCommand), stages the listen-server host's uplink via StageLocalUplinkBlock, and calls BeginFastForward; ⑥ UMassBattleEntityComponentBase allocates/registers/unregisters LockstepNetIDs. downstream — this subsystem drives: template registration in the factories (AgentSubsystem/LootSubsystem/ProjectileSubsystem/HostSubsystem skeleton and DA templates), component RebindToEntity, AgentSubsystem::RebindLocalVisualsAfterResync and BP task rebuild inside ProcessDeferredSnapshot, and HostSubsystem pool push-back / sound-concurrency rebuild / host refresh plus HashGrid::ResetOccupiedAgentCells inside ApplyEntitySnapshotPayload; resync requests go up via NetPC::ServerRequestResync and snapshots come down via the TCP callback into QueueSnapshotApply.

补充说明 Notes

① 策略枚举 TemplateReference / RuntimeObjectRebuild 已声明但当前 GetSnapshotFieldPolicy 从不产生(预留);RuntimeObjectLocalOnly 与 UnsupportedTransient 被布局宏排除出 blob。 ② FMassBattleNetworkEventData.FFTicks 与 bHashMatched 字段在全部发射点均未被填充(声明预留)。 ③ MinNetworkTickSpeedRatio 未参与当前 UpdateNetworkClientPacing 的比率计算(减速硬编码 lerp 到 0.3)。 ④ GetNetworkStats 的 LastSnapshotSizeBytes 恒为 0——按需 resync 无定期快照。 ⑤ LogDesyncDetails 仅在 WITH_EDITOR 构建生效。

① The policies TemplateReference / RuntimeObjectRebuild are declared but never produced by the current GetSnapshotFieldPolicy (reserved); RuntimeObjectLocalOnly and UnsupportedTransient are excluded from the blob by the layout macro. ② FMassBattleNetworkEventData.FFTicks and bHashMatched are not filled by any emit site (declared, reserved). ③ MinNetworkTickSpeedRatio does not participate in the current UpdateNetworkClientPacing ratio math (deceleration lerps to a hardcoded 0.3). ④ GetNetworkStats' LastSnapshotSizeBytes is always 0 — on-demand resync has no periodic snapshot. ⑤ LogDesyncDetails only works in WITH_EDITOR builds.