MassBattle Docsv1.19.20

MassBattleSnapshotStructs.h

USTRUCT ×8

Source/MassBattle/Public/Network/MassBattleSnapshotStructs.h

概述 Overview

Agent 快照结构体集合,实现 TemplateIdentity + RuntimeOverlay 模型:FEntitySnapshotRecord 只携带模板 Key 与 UID(身份)加运行时 overlay blob(状态),不携带 archetype 组合本身——恢复端从本地确定性模板注册表按 Key 取回模板再应用 overlay。顶层 FEntitySnapshotPayload 是经 TCP 侧通道发送的完整快照:实体列表 + UID 分配器占用计数与铸造游标 + 双随机流 + 挂起命令/deferred 生成请求/gap 命令 + 任务记录与 ID 计数器 + LockstepVarStore 快照 + 随快照本体派发的流场基底(FFlowFieldSubstrateEntry)。所有结构均为 BlueprintType,但实际序列化走 FStructSerializer(见 MassBattleSnapshotTcpTransport.html)。

Agent snapshot struct collection implementing the TemplateIdentity + RuntimeOverlay model: FEntitySnapshotRecord carries only a template Key and UID (identity) plus runtime overlay blobs (state) — not the archetype composition itself; the restore side fetches the template from the local deterministic registry by Key and applies the overlay on top. The top-level FEntitySnapshotPayload is the complete snapshot sent over the TCP side-channel: entity list, UID-allocator occupied count and mint cursor, two random streams, pending commands / deferred spawn requests / gap commands, task records and ID counters, LockstepVarStore snapshots, plus the flow-field substrates riding the snapshot itself (FFlowFieldSubstrateEntry). All structs are BlueprintType, but actual serialization goes through FStructSerializer (see MassBattleSnapshotTcpTransport.html).

FFragmentSnapshotBlob USTRUCT

单个 fragment 的序列化快照属性——按注册表布局排列的扁平字节 blob。

Per-fragment serialized snapshot properties — a flat blob of bytes ordered by the registry layout.

成员变量 Members

名称 Name类型 Type默认值说明 Description
DataTArray<uint8>空快照属性值的扁平化 blob。Flat blob of snapshot property values.

FFragmentSnapshotBlobEntry USTRUCT

网络安全的 fragment blob 键值对:FragmentName(fragment 结构名,如 "FMoving",或 LockstepVarStore 中的变量名)+ Blob。恢复端按名匹配布局,增删安全。

Network-safe key/value pair for fragment blobs: FragmentName (the fragment struct name, e.g. "FMoving", or a variable name in LockstepVarStore) plus Blob. Restore matches by name against the layout, so additions/removals stay safe.

成员变量 Members

名称 Name类型 Type默认值说明 Description
FragmentNameFName—fragment 名(或变量名)。Fragment (or variable) name.
BlobFFragmentSnapshotBlob—对应 blob。The corresponding blob.

FVarStoreSnapshotEntry USTRUCT

LockstepVarStore 快照(每个模板实例一条):TemplateKey 解析实例,Fields 每变量一条(恢复按名匹配——BP 变量增删安全)。由 UMassBattleSubsystem::CaptureVarStoreBlobs 按确定性键序生成。

Lockstep variable store snapshot (one per template instance): TemplateKey resolves the instance; Fields holds one entry per variable (name-matched on restore — BP variable add/remove stays safe). Produced by UMassBattleSubsystem::CaptureVarStoreBlobs in deterministic key order.

成员变量 Members

名称 Name类型 Type默认值说明 Description
TemplateKeyFName—模板 BP 类路径(UMassBattleBPTaskTemplateBase 子类)。Template BP class path (UMassBattleBPTaskTemplateBase subclass).
FieldsTArray<FFragmentSnapshotBlobEntry>空每个同步变量一条,FragmentName = 变量名。One entry per synced variable — FragmentName = variable name.

FEntityRuntimeOverlay USTRUCT

实体运行时状态的动态 blob 快照。使用 TArray 条目保证快照序列化的确定性顺序。仅注册在快照字段注册表中的 fragment 有 entry。

Dynamic blob-based snapshot of entity runtime state. Uses TArray entries for deterministic ordering in snapshot serialization. Only fragments registered in the snapshot field registry have entries.

成员变量 Members

名称 Name类型 Type默认值说明 Description
FragmentBlobsTArray<FFragmentSnapshotBlobEntry>空每个 fragment 的快照 blob(FragmentName = fragment 结构名,如 "FMoving")。Per-fragment snapshot blobs (FragmentName = fragment struct name, e.g. "FMoving").
SharedFragmentBlobsTArray<FFragmentSnapshotBlobEntry>空shared fragment 快照 blob。按实体捕获(per-chunk 值复制),在 BuildEntity 之前经 SetSharedFragment 恢复到模板 shared fragment(写时复制 + 按值去重)。Per-shared-fragment snapshot blobs. Captured per-entity (per-chunk value replicated), restored into template shared fragments BEFORE BuildEntity via SetSharedFragment (copy-on-write + value dedup).

FEntitySnapshotRecord USTRUCT

快照 payload 中的单个实体记录。TemplateIdentity(TemplateKey + UniqueID)在本地确定性注册表中定位模板,RuntimeOverlay 携带运行时状态;EntityType 为权威主实体类别(主类型 tag 仍仅作 processor 查询索引);TagDelta 为 archetype tag 增量位掩码。

Single entity record in a snapshot payload. TemplateIdentity (TemplateKey + UniqueID) locates the template in the local deterministic registry; RuntimeOverlay carries runtime state; EntityType is the authoritative main entity category (main type tags remain processor query indexes); TagDelta is the archetype tag delta bitmask.

成员变量 Members

名称 Name类型 Type默认值说明 Description
TemplateKeyFName—模板标识——在本地确定性注册表中查找的键。TemplateIdentity — lookup key into the local deterministic registry.
UniqueIDint32-1稳定身份,用于跨实体句柄修复(-1 = 无效)。Stable identity for cross-entity handle fixups (-1 = invalid).
EntityTypeEEMainTypeAgent权威主实体类别;主类型 tag 仍仅作 processor 查询索引。Authoritative main entity category; main type tags remain processor query indexes.
TagDeltauint160Archetype tag 增量位掩码(bit0=Appearing, bit1=Dying, bit2=Destroying)。内部位掩码——由 MB_SNAP_TAG_DELTA_* 宏捕获/应用,不对 Blueprint 暴露(UHT 不支持 BP uint16)。Archetype tag delta bitmask (bit0=Appearing, bit1=Dying, bit2=Destroying). Internal bitmask — captured/applied by the MB_SNAP_TAG_DELTA_* macros, not Blueprint-visible (uint16 is unsupported by UHT for BP).
FlagsLowint640完整 flag 快照低位。Full flag snapshot, low word.
FlagsHighint640完整 flag 快照高位。Full flag snapshot, high word.
RuntimeOverlayFEntityRuntimeOverlay—运行时 POD overlay。Runtime POD overlay.

FDeferredAgentSpawnSnapshot USTRUCT

deferred(分批)agent 生成请求的快照形态——确定性挂起状态:命令已执行、分批未完成。resync 时恢复,防止队列进度与已累计 UID 漂移。字段镜像生成请求的完整参数(位置列表、数量、队伍、发射速度、初始朝向、地面 trace 参数、子步进进度、已累计 UID)。

Snapshot form of a deferred (batched) agent spawn request — deterministic pending state: the command executed, batches not yet emitted. Restored on resync so queue progress and accumulated UIDs do not drift. Fields mirror the full spawn-request parameter set (location list, quantity, team, launch velocity, initial rotation, ground-trace parameters, substep progress, accumulated UIDs).

成员变量 Members

名称 Name类型 Type默认值说明 Description
TemplateKeyFName—在 SnapshotTemplateRegistry 中查找(与实体恢复同机制)。Lookup key into SnapshotTemplateRegistry (same mechanism as entity restore).
LocationsTArray<FVector>空待生成的批次位置列表。Batch spawn location list.
Quantityint320总数量。Total quantity.
Teamint320队伍。Team.
LaunchVelocityFVector2DZeroVector发射速度。Launch velocity.
InitialRotationEInitialRotationFacePlayer初始朝向模式。Initial rotation mode.
CustomRotationFRotatorZeroRotator自定义朝向(朝向模式为 Custom 时)。Custom rotation (when the mode is Custom).
MultipliersFSpawnerMult—生成器倍率。Spawner multipliers.
GroundTraceChannelTEnumAsByte<ECollisionChannel>ECC_WorldStatic地面 trace 碰撞通道。Ground-trace collision channel.
GroundTraceHeightRangeFVector2D(1000.f, -1000.f)地面 trace 高度范围。Ground-trace height range.
GroundObjectTypesTArray<TEnumAsByte<EObjectTypeQuery>>空地面对象类型查询列表。Ground object type queries.
ObstacleObjectTypesTArray<TEnumAsByte<EObjectTypeQuery>>空障碍物对象类型查询列表。Obstacle object type queries.
MaxSlopeCosinefloat0.f最大坡度余弦。Max slope cosine.
bAutoActivatedbooltrue是否自动激活。Whether auto-activated.
Substepsint320子步进数(>0 时分批生成)。Substep count (>0 = batched spawn).
bFirstTickPendingboolfalse为 true 时本 tick 跳过处理并置 false(Substeps>0 用于延迟启动到下一帧)。When true, skip processing this tick and set to false (used for Substeps>0 to delay the start to next frame).
CurrentSubstepIndexint320当前子步进索引。Current substep index.
NextLocationIndexint320下一个待生成位置索引。Next location index to spawn.
AccumulatedUIDsTArray<int32>空已累计句柄以 UID 序列化——恢复时反解为句柄。Accumulated handles serialized as UIDs — resolved back to handles on restore.

FFlowFieldSubstrateEntry USTRUCT

随快照派发的一份流场基底——服务器缓存拷贝,对快照系统为不透明字节。派发时(而非周期捕获时)从服务器缓存填充到 FEntitySnapshotPayload::FlowFieldSubstrates;应用端在实体重建之前按 FieldName 找到地图上的 AFlowField 并导入,保证新加入/恢复中的客户端不会在无导航基底的状态下模拟任何 tick。结构体必须声明在 FEntitySnapshotPayload 之前(UHT 哈希序要求)。

One flow-field substrate riding a snapshot dispatch — a server-cache copy that is opaque bytes to the snapshot system. Filled into FEntitySnapshotPayload::FlowFieldSubstrates at dispatch time (never captured periodically) from the server cache; the apply side imports it into the map-placed AFlowField (matched by FieldName) BEFORE the entity restore, so a fresh/recovering client never simulates a tick without its navigation substrate. The struct must be declared before FEntitySnapshotPayload (UHT hash order).

成员变量 Members

名称 Name类型 Type默认值说明 Description
FieldNameFName—地图摆放的 AFlowField Actor 名——应用端的联结键。Map-placed AFlowField actor name — the import-side join key.
BytesTArray<uint8>空紧凑量化基底流(FlowFieldCanvas 格式)——对快照系统不透明。Compact quantized substrate stream (FlowFieldCanvas format) — opaque to the snapshot system.

FEntitySnapshotPayload USTRUCT

通过 TCP 侧通道发送的实体快照 payload——快照的顶层容器。除实体列表外,携带使恢复端与捕获端逐位一致的全部全局状态:UID 分配器占用计数与单调铸造游标、双随机流、挂起命令、deferred 生成请求、gap 命令、BP 异步任务记录与任务 ID 计数器、LockstepVarStore 快照,以及随快照本体派发的流场基底。

Entity snapshot payload sent via the TCP side-channel — the top-level snapshot container. Besides the entity list it carries all global state needed to make the restore side bit-identical to the capture side: UID-allocator occupied count and monotonic mint cursor, two random streams, pending commands, deferred spawn requests, gap commands, BP async task records with task ID counters, LockstepVarStore snapshots, and the flow-field substrates riding the snapshot dispatch.

成员变量 Members

名称 Name类型 Type默认值说明 Description
TickCountint320快照捕获 tick。Tick at which the snapshot was captured.
ServerHashAtCaptureint640服务器捕获 tick 的每帧 hash——resync 校准基准(恢复端折叠结果与之比对)。Server's per-tick hash at the capture tick — the resync calibration baseline (the restore-side fold is compared against it).
UIDOccupiedCountint32-1捕获时通用实体分配器的占用计数——哈希折叠指纹(NetworkProcessor 折叠 GetNumOccupied,恢复校验在重建后镜像折叠);分配器位图本身不是快照状态,经 ReconcileUIDAllocator 从重建映射收敛。取代退役的 NextGlobalUID 计数器(槽位分配 + 循环利用,2026-08-16)。General-entity allocator occupied count at capture — the hash-fold fingerprint (NetworkProcessor folds GetNumOccupied; restore validation mirrors it after reconciliation). The allocator bitmap itself is not snapshot state: it converges via ReconcileUIDAllocator from the rebuilt map. Replaces the retired NextGlobalUID counter (slot allocator with recycling, 2026-08-16).
UIDCursorint32-1捕获时的单调铸造前沿(高水位游标,2026-09-11)。与占用位图(从重建映射推导)不同,游标是独立锁步状态:只在确定性铸造点推进,必须原样恢复(捕获取 EntityUIDAllocator.GetCursor(),恢复经 SetCursor),恢复后(追帧/补 gap)的铸造才能落在服务器本会分配的位置。-1 = 单调化之前服务器的旧载荷(恢复端改为从占用推导游标)。Monotonic mint frontier at capture (high-watermark cursor, 2026-09-11). Unlike the occupancy bitmap (derived from the rebuilt map), the cursor is independent lockstep state: it only advances at deterministic mint points and must be restored verbatim (captured from EntityUIDAllocator.GetCursor(), restored via SetCursor) so post-restore (FF/gap) mints land exactly where the server's would. -1 = legacy payload from a pre-monotonic server (the restoring peer derives the cursor from occupancy instead).
AgentRandomStreamFRandomStream—agent 随机流快照。Agent random stream snapshot.
HashGridRandomStreamFRandomStream—hash 网格随机流快照。Hash-grid random stream snapshot.
PendingCommandsTArray<FMassBattleNetCommand>空挂起命令列表(快照应用后继续执行的命令队列状态)。Pending command list (the queue state that continues after the snapshot apply).
DeferredSpawnRequestsTArray<FDeferredAgentSpawnSnapshot>空deferred(分批)agent 生成请求——resync 时恢复(确定性挂起状态)。Deferred (batched) agent spawn requests — restored on resync (deterministic pending state).
EntitiesTArray<FEntitySnapshotRecord>空实体记录列表。Entity record list.
HandleFixupsTArray<FEntityHandleFixup>空预留给将来的跨实体句柄修复。Reserved for future cross-entity handle fixups.
GapCommandsTArray<FMassBattleNetCommand>空快照 tick 到当前 tick 之间已执行的命令(从 CommandHistory 填充),客户端 FF 期间重放。Commands executed between the snapshot tick and the current tick (filled from CommandHistory), replayed by the client during FF.
TaskRecordsTArray<FAgentTaskSnapshotRecord>空BP 异步任务记录——应用时旧任务被终止,经模板重建(TemplateKey → 重新绑定 delegate)。BP async task records — old tasks are terminated on apply and rebuilt via their templates (TemplateKey → re-bind delegates).
NextMoveToTaskIDint321任务 ID 计数器——恢复以保证双端为后续任务创建命令发放相同 ID。Task ID counter — restored so both peers mint identical IDs for future task-creation commands.
NextChaseAttackTaskIDint321ChaseAttack 任务 ID 计数器。ChaseAttack task ID counter.
LockstepVarStoresTArray<FVarStoreSnapshotEntry>空LockstepVarStore 快照——每个模板实例一条(TemplateKey → 实例,Fields → 逐变量值)。在 ApplyEntitySnapshotPayload 中恢复(先于恢复 hash 校验——恢复折叠镜像采集折叠)。LockstepVarStore snapshots — one entry per template instance (TemplateKey → instance, Fields → per-variable values). Restored in ApplyEntitySnapshotPayload (before the restore hash validation — the restore fold mirrors the capture fold).
FlowFieldSubstratesTArray<FFlowFieldSubstrateEntry>空随快照本体派发的流场基底(2026-09-09 基底时序保证):派发时从服务器缓存填充(绝不周期捕获);应用端在实体重建之前导入——新客户端/恢复客户端绝不会在无导航基底的状态下模拟任何 tick。命令通道补发要 K+defer tick 后才落地;窗口期寻路会分叉 PathPoints(直线回退 vs 服务器的基底 A*)。Flow-field substrates riding the snapshot itself (2026-09-09 substrate ordering guarantee): filled at dispatch time from the server cache (never captured periodically); imported by the apply side BEFORE the entity restore — a fresh/recovering client never simulates a tick without its navigation substrate. Command-channel re-delivery would land K+defer ticks after resume; pathing in that window forks PathPoints (straight-line fallback vs the server's substrate A*).

管线角色 Pipeline Role

采集:捕获 tick(bCaptureSnapshot)由 UMassBattleNetworkProcessor 构建 FEntitySnapshotPayload——实体记录按快照注册表布局序列化(MassBattleSnapshotRegistry.h),LockstepVarStore 条目由 UMassBattleSubsystem::CaptureVarStoreBlobs 生成,UIDCursor 取自 EntityUIDAllocator.GetCursor(),缓存为 UMassBattleNetworkSubsystem::CachedLatestSnapshot 供 resync/late-join 派发。 传输:服务器侧 DispatchSnapshotViaTcp_Async(GameModeBase)在后台线程经 FMassBattleSnapshotTcpTransport::SerializeSnapshotPayload + CompressSnapshot 序列化压缩,游戏线程非阻塞发送;派发时从服务器流场缓存填充 FlowFieldSubstrates;客户端 OnSnapshotBytesReceived 回调反序列化后 QueueSnapshotApply。 恢复:ApplyEntitySnapshotPayload(NetworkSubsystem)先按 FieldName 把流场基底导入地图上的 AFlowField(早于实体重建,并写入本端缓存供重放块旁路)→ 按 TemplateKey 取模板 → 应用 RuntimeOverlay(含 SharedFragmentBlobs 的 SetSharedFragment)→ 恢复 UID 游标(原样 SetCursor)/随机流/任务记录/挂起命令 → DeserializeFromEntries 恢复 LockstepVarStore → 恢复 hash 折叠与 ServerHashAtCapture 比对(不匹配拒绝应用,fail loud)。

Capture: on capture ticks (bCaptureSnapshot) UMassBattleNetworkProcessor builds the FEntitySnapshotPayload — entity records serialize per the snapshot registry layout (MassBattleSnapshotRegistry.h); LockstepVarStore entries come from UMassBattleSubsystem::CaptureVarStoreBlobs; UIDCursor is taken from EntityUIDAllocator.GetCursor(); the result is cached as UMassBattleNetworkSubsystem::CachedLatestSnapshot for resync/late-join dispatch. Transport: the server-side DispatchSnapshotViaTcp_Async (GameModeBase) serializes and compresses on a background thread via FMassBattleSnapshotTcpTransport::SerializeSnapshotPayload + CompressSnapshot, then sends non-blocking on the game thread; FlowFieldSubstrates are filled from the server's flow-field cache at dispatch time; the client's OnSnapshotBytesReceived callback deserializes and calls QueueSnapshotApply. Restore: ApplyEntitySnapshotPayload (NetworkSubsystem) first imports the flow-field substrates into the map-placed AFlowField by FieldName (before the entity restore, also caching them locally for the replay block-bypass) → fetches the template by TemplateKey → applies the RuntimeOverlay (including SetSharedFragment for SharedFragmentBlobs) → restores the UID cursor (verbatim SetCursor) / random streams / task records / pending commands → restores LockstepVarStores via DeserializeFromEntries → runs the restore-hash fold and compares against ServerHashAtCapture (mismatch rejects the apply, fail loud).

补充说明 Notes

FMassBattlePlayerSpawnSnapshotRecord 已移除——玩家身份现由快照内每个 agent 的 FAgentController::OwningPlayerSlot 携带,AgentComponent 在快照应用时经 RebindToEntity 自重链,不再需要独立的每玩家记录。

FMassBattlePlayerSpawnSnapshotRecord is removed — player identity is now carried by each agent's FAgentController::OwningPlayerSlot inside the snapshot, and AgentComponents re-link themselves via RebindToEntity on snapshot apply; no separate per-player record is needed.

ObstacleSpawnManifest(late-join 障碍物生成清单)已于 2026-08-28 移除——命令路由障碍物现已是快照公民(FNetworkTag + 合成模板键,随 Entities 走)。旧清单重放死于两个 bug:ExecuteTick 把清单命令重盖为客户端本地 tick(≤ PayloadTick,被队列重建 RemoveAll 抹除)与共享 ServerExecSequence=0 的去重键碰撞(只放行第一条命令)。

ObstacleSpawnManifest (the late-join obstacle spawn manifest) was removed on 2026-08-28 — command-routed obstacles are snapshot citizens now (FNetworkTag + synthetic template keys; they ride Entities). The old manifest replay died to two bugs: ExecuteTick restamped manifest commands to the client-local tick (≤ PayloadTick → wiped by the queue-rebuild RemoveAll), and the shared ServerExecSequence=0 dedupe-key collision admitted only the first command.