host_runtime.h 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <optional>
  6. #include <span>
  7. #include <vector>
  8. #include "../../middleware/bap/activity_message/cinematic_incident.h"
  9. #include "../../middleware/bap/activity_message/incident.h"
  10. #include "../../middleware/bap/activity_message/player_trigger_incident.h"
  11. #include "../../middleware/bap/activity_message/scriptable_auth_body.h"
  12. #include "../../middleware/bap/activity_message/sense_update.h"
  13. #include "../../middleware/bap/activity_message/sensor_auth_update.h"
  14. #include "../../middleware/bap/activity_message/squad_auth_body.h"
  15. #include "../../middleware/bap/activity_message/squad_sense_state.h"
  16. #include "../../state/activity/definition.h"
  17. #include "../../state/activity/receipts/definition.h"
  18. #include "../../state/build_data/scenarios/definition.h"
  19. #include "../../state/gameplay/external/squad_entity_retirement.h"
  20. namespace sunrise::server::activity::host {
  21. using AuthoredSceneDependencies =
  22. middleware::bap::activity_message::sensor_auth_update::AuthoredSceneDependencies;
  23. /** Activity instances tracked by the diagnostic host. */
  24. inline constexpr std::size_t kInstanceCapacity = state::activity::kSessionCapacity;
  25. /** Recent normalized events retained for the panel and HUD. */
  26. inline constexpr std::size_t kEventCapacity = 64;
  27. /**
  28. * Accepted client mission inputs copied in one paged feed read. The feed itself is unbounded:
  29. * the reader loops until it is empty, so this only sizes one copy.
  30. */
  31. inline constexpr std::size_t kMissionInputReadPageSize = 64;
  32. /** Parsed inbound and outbound incidents retained for inspection and field replay. */
  33. inline constexpr std::size_t kIncidentHistoryCapacity = 32;
  34. /** Owned client messages retained as framing metadata for diagnostics. */
  35. inline constexpr std::size_t kClientMessageHistoryCapacity = 512;
  36. /** Decoded packet details retained separately from the high-volume metadata history. */
  37. inline constexpr std::size_t kClientMessageDetailCapacity = 64;
  38. /** Latest complete msg-6 object observations retained for one activity generation. */
  39. inline constexpr std::size_t kSenseObservationCapacity =
  40. middleware::bap::activity_message::sense_update::kDecodedObjectCapacity;
  41. /** Typed values owned by the retained msg-6 observations for one activity generation. */
  42. inline constexpr std::size_t kSenseObservationValueCapacity =
  43. middleware::bap::activity_message::sense_update::kDecodedValueCapacity;
  44. /** Per-slot counts the squad Sense body can carry. Its nested array is eight elements. */
  45. inline constexpr std::size_t kSquadSlotCapacity = 8;
  46. /** Objective task groups a squad publishes one cost for. */
  47. inline constexpr std::size_t kSquadObjectiveGroupCount = 24;
  48. /** Distinct exact ClientRef counters retained for one activity generation. */
  49. inline constexpr std::size_t kScriptableGuardCapacity =
  50. state::build_data::scenarios::kRosterSlotCapacity;
  51. /** State-local SDK groups are carried with the request instead of indexing the baseline census. */
  52. inline constexpr std::uint16_t kGeneratedRosterGroupIndex = 0xFFFFU;
  53. /** No generated SDK object backs this ordinary canonical roster target. */
  54. inline constexpr std::uint32_t kNoSdkObjectIndex = 0xFFFFFFFFU;
  55. /** Proved spawn-gate-passing type-17 lifetime state used before an operator transition. */
  56. inline constexpr std::uint8_t kDefaultLifetimeState = 3;
  57. /** Lifetime state that shows the loading presentation and refuses the native spawn gate. */
  58. inline constexpr std::uint8_t kLoadingLifetimeState = 4;
  59. /** Highest lifetime state inside the client's jump table. */
  60. inline constexpr std::uint8_t kMaximumLifetimeState =
  61. middleware::bap::activity_message::sensor_auth_update::kMaximumLifetimeState;
  62. /** Events visible at the Activity Host boundary. */
  63. enum class EventKind : std::uint8_t {
  64. /** One bounded msg 6 decode entered the host reducer. */
  65. senseUpdate = 0,
  66. /** One committed client msg 22 changed safe numeric State. */
  67. clientStateChanged = 1,
  68. /** One owned client envelope without a richer typed mission event entered the host reducer. */
  69. clientMessageReceived = 2,
  70. /** An operator state push committed with its pending output. */
  71. authStateCommitted = 3,
  72. /** A msg 5 carrying the committed state reached the transport output queue. */
  73. authStateTransportStaged = 4,
  74. /** A pending output lost its exact activity generation and was canceled. */
  75. authStateCanceled = 5,
  76. /** One validated client msg 19 was captured with all bounded fields. */
  77. incidentReceived = 6,
  78. /** One operator msg 19 was accepted into the ordered output history. */
  79. incidentQueued = 7,
  80. /** One queued msg 19 reached a matching link's transport output queue. */
  81. incidentTransportStaged = 8,
  82. /** One unstaged msg 19 lost its exact activity generation. */
  83. incidentCanceled = 9,
  84. /** One queued operator msg 19 was refused during the service slice. */
  85. incidentRefused = 10,
  86. /** One typed ClientRef body entered the serialized output slot. */
  87. scriptableOverrideCommitted = 11,
  88. /** One typed ClientRef body reached the transport output queue. */
  89. scriptableOverrideTransportStaged = 12,
  90. /** One unstaged ClientRef body lost its exact activity generation. */
  91. scriptableOverrideCanceled = 13,
  92. /** An operator request was refused without changing state. */
  93. operatorRefused = 14,
  94. /** One authoritative Mission State timer became due; this is not a Host feed row. */
  95. timerElapsed = 15,
  96. /** One script effect reached a terminal delivery state; this is not a Host feed row. */
  97. effectResult = 16,
  98. /** One committed mission phase change; this is not a Host feed row. */
  99. phaseEntered = 17,
  100. /** A watched trigger volume became occupied; derived from one msg 6 body. */
  101. triggerEntered = 18,
  102. /** A watched trigger volume became empty; derived from one msg 6 body. */
  103. triggerExited = 19,
  104. /** One squad's published counters changed; derived from one msg 6 body. */
  105. squadState = 20,
  106. /** One squad per-slot count rose; derived from one msg 6 body. */
  107. entitySpawned = 21,
  108. /** One squad alive count fell; derived from one msg 6 body. */
  109. entityDied = 22,
  110. /** A watched authored scene latched complete; derived from one msg 6 body. */
  111. sceneFinished = 23,
  112. /** One watched objective task counter rose; derived from one msg 6 body. */
  113. objectiveProgress = 24,
  114. /** Msg 20 reported the exact number of additional simulation-entity indices requested. */
  115. entitySlotsRequested = 25,
  116. /** Another committed session bound to this destination; this is not a Host feed row. */
  117. sessionJoined = 26,
  118. /** A watched peer session left this destination; this is not a Host feed row. */
  119. sessionLeft = 27,
  120. /** One schema-0x8080879F msg-19 target resolved to its authored type-31 source. */
  121. playerTrigger = 28,
  122. /** One schema-0x808087BF msg-19 reports that an exact authored Type-6 slot started. */
  123. cinematicStarted = 29,
  124. /** One schema-0x808087BF msg-19 reports Type-6 start failure or runtime termination. */
  125. cinematicTerminated = 30,
  126. /** Accepted native Ghost interaction progress for one exact type-65 slot. */
  127. ghostLinkState = 31,
  128. /** A named actor's movement or delivery level changed. */
  129. actorPathState = 32,
  130. /** The client accepted a player's use of one interactable object. */
  131. objectInteracted = 33,
  132. /** Native cinematic_skip incident for an exact Type-6 source. */
  133. cinematicSkipRequested = 34,
  134. /** Life counts of the private activity's joined party changed. */
  135. fireteamState = 35,
  136. /** An interactable object's presence, alive or ownership level changed. */
  137. objectState = 36,
  138. /** A damage monitor published new health, shield or revision values. */
  139. damageState = 37,
  140. /** A gameplay policy accepted the first damage to an exact selected squad. */
  141. squadProvoked = 38,
  142. /** A device reported changed current channel values or accepted sequences. */
  143. deviceState = 39,
  144. /** An accepted client report moved the held region to another authored region. */
  145. regionChanged = 40,
  146. /** A watched authored scene newly reported one of its output gates; from one msg 6 body. */
  147. sceneOutput = 41,
  148. /** Validated type-30 level or explicit continuity invalidation. */
  149. triggerState = 42,
  150. };
  151. /** Kinds are numbered without gaps, so the last one plus one is the count. */
  152. inline constexpr std::size_t kEventKindCount =
  153. static_cast<std::size_t>(EventKind::triggerState) + 1U;
  154. /**
  155. * Terminal delivery outcome of one script-requested effect.
  156. * Transport staging is the strongest outcome the server can prove. No outcome here says the stock
  157. * client applied the effect, because the client sends no acknowledgement for one.
  158. */
  159. enum class EffectOutcome : std::uint8_t {
  160. /** The carrying message reached the transport output queue. */
  161. transportStaged,
  162. /** The host refused the request and committed no state. */
  163. refused,
  164. /** The request passed its delivery deadline before it staged. */
  165. expired,
  166. /** The request lost its exact activity generation before it staged. */
  167. canceled,
  168. };
  169. /** Latest attempt to place one committed operator output onto its normal BAP path. */
  170. enum class OutputStatus : std::uint8_t {
  171. idle,
  172. pending,
  173. waitingForEpoch,
  174. noLayout,
  175. noGroups,
  176. noOverrideTarget,
  177. ambiguousLinks,
  178. frameRefused,
  179. transportStaged,
  180. canceled,
  181. };
  182. /** One serialized operator output slot preserves msg-5/msg-19 order. */
  183. enum class OutputKind : std::uint8_t {
  184. none,
  185. authState,
  186. incident,
  187. scriptableOverride,
  188. };
  189. /** Full ClientRef slot identity used for counters and transport acknowledgements. */
  190. struct ScriptableTarget final {
  191. std::uint32_t objectTag{};
  192. std::uint32_t registryKey{};
  193. std::uint32_t authSchema{};
  194. /** Canonical installed roster-table row proved against the whole package object layout. */
  195. std::uint16_t rosterGroupIndex{};
  196. /** Canonical slot-array offset proved against this exact slot index and type. */
  197. std::uint16_t rosterSlotOffset{};
  198. std::uint16_t slotIndex{};
  199. /** Generated object row owning an inline state-local group, or the absent sentinel. */
  200. std::uint32_t sdkObjectIndex{kNoSdkObjectIndex};
  201. /** Exact full slice-set index for a state-local group, or -1 for a published group. */
  202. std::int32_t stateLocalRegion{-1};
  203. std::uint8_t slotType{};
  204. /** This group is safe only in the exact selected state pinned by the requesting link. */
  205. bool stateLocalRoster{};
  206. };
  207. /** Exact unarmed Host output lane held while Mission State publishes its matching revision. */
  208. struct ScriptableOutputReservation final {
  209. state::activity::SessionBinding binding{};
  210. std::uint64_t resetGeneration{};
  211. std::uint64_t token{};
  212. std::uint64_t revision{};
  213. /** Durable Mission State head, or zero for an operator-only reservation. */
  214. std::uint64_t intentSequence{};
  215. };
  216. /** Atomic disposition of one exact queued durable Mission output. */
  217. enum class ScriptableWithdrawStatus : std::uint8_t {
  218. /** The exact queued reducer row was tombstoned before it could commit. */
  219. withdrawn,
  220. /** No exact row or output exists and the Host revision is still below the assignment. */
  221. absent,
  222. /** The exact Host output is committed and still waiting for transport. */
  223. committed,
  224. /** The exact Host output already reached transport. */
  225. transportStaged,
  226. /** The exact Host revision committed and was canceled before transport. */
  227. canceled,
  228. /** The Host advanced beyond the assigned revision. */
  229. advanced,
  230. /** The binding, assignment, or serialized lane did not match exactly. */
  231. mismatch,
  232. };
  233. /** Typed scriptable body occupying one instance's serialized output slot. */
  234. enum class ScriptableOverrideKind : std::uint8_t {
  235. squad,
  236. combatantChannel,
  237. combatantBinding,
  238. object,
  239. sequence,
  240. cinematic,
  241. type23,
  242. type31,
  243. objectiveReset,
  244. task,
  245. authoredScene,
  246. dialogue,
  247. sdkAuth,
  248. /** Activity lifetime state. It carries no body; the msg-5 builder writes the type-17 block. */
  249. lifetime,
  250. /** Type-42 performance start: one state name behind a rising per-slot generation. */
  251. performance,
  252. authoredSceneEvent,
  253. authoredSceneStop,
  254. combatantSequence,
  255. squadObjective,
  256. combatantProgram,
  257. combatantRetirement,
  258. interactableObject,
  259. damageWatch,
  260. /** Type-65 Ghost-link scan: the host owns its generation and finishes its bar. */
  261. ghostLink,
  262. };
  263. /** The client stalls one frame short of the duration, so this reported fraction is the bar's end.
  264. */
  265. inline constexpr float kGhostLinkFinishFraction = 0.99F;
  266. /** Current diagnostic state of one retained incident. */
  267. enum class IncidentStatus : std::uint8_t {
  268. received,
  269. queued,
  270. encodeFailed,
  271. frameRefused,
  272. transportStaged,
  273. canceled,
  274. };
  275. /** What the diagnostic route proved about one owned client body. */
  276. enum class ClientMessageStatus : std::uint8_t {
  277. unclassified,
  278. /** The complete declared body was decoded. */
  279. decoded,
  280. /** The complete framing closed, but one or more selected values were skipped. */
  281. decodedPartial,
  282. /** A typed prefix was decoded and the remaining body is opaque. */
  283. prefixOnly,
  284. /** The declared body is bounded, but its inner grammar is not known. */
  285. opaque,
  286. /** The msg-19 outer fields decoded, while its target-selected schema remains opaque. */
  287. outerDecoded,
  288. /** A transaction accepted the body, but diagnostics kept no parser depth. */
  289. prepared,
  290. /** The body parser accepted its input, but State or transaction preparation refused it. */
  291. prepareRefused,
  292. malformed,
  293. quarantined,
  294. };
  295. /** Copied msg-6 fields submitted after envelope and session validation. */
  296. struct SenseInput final {
  297. state::activity::SessionBinding binding{};
  298. /** ActivityClient generation that owned the inbound message. */
  299. std::uint64_t sourceGeneration{};
  300. /** Protocol ingress row for this same envelope. */
  301. std::uint64_t clientMessageSequence{};
  302. std::uint64_t epochFirst{};
  303. std::uint64_t epochSecond{};
  304. std::uint32_t payloadBytes{};
  305. std::uint32_t peerHeardMask{};
  306. std::uint32_t tailBits{};
  307. std::uint32_t consumedBits{};
  308. std::uint32_t firstGroupBits{};
  309. std::uint32_t firstRegistryKey{};
  310. std::uint32_t groupsSeen{};
  311. std::uint32_t groupsDecoded{};
  312. std::uint32_t groupsSkipped{};
  313. std::uint32_t objectsSeen{};
  314. std::uint32_t objectsDecoded{};
  315. std::uint16_t firstSlotIndex{};
  316. std::uint8_t firstSlotType{};
  317. middleware::bap::activity_message::sense_update::DecodeStatus decodeStatus{
  318. middleware::bap::activity_message::sense_update::DecodeStatus::malformed};
  319. state::activity::receipts::Verdict verdict{state::activity::receipts::Verdict::absent};
  320. /** Complete value-owned decode copied before decrypted transport storage is cleared. */
  321. middleware::bap::activity_message::sense_update::DecodedPacket decoded{};
  322. bool hasFirstObject{};
  323. std::uint64_t attemptGeneration{};
  324. };
  325. /** Exact package and schema identity for one observed Sense ClientRef. */
  326. struct SenseObservationKey final {
  327. std::uint32_t registryKey{};
  328. std::uint32_t objectTag{};
  329. std::uint32_t senseSchema{};
  330. std::uint32_t schemaRow{middleware::bap::activity_message::sense_update::kAbsentRuntimeRow};
  331. std::uint16_t slotIndex{};
  332. std::uint8_t slotType{};
  333. };
  334. /** Copies the squad's merged recovery state for this exact ActivityClient generation. */
  335. [[nodiscard]] bool
  336. snapshot_squad_sense(const state::activity::SessionBinding& binding,
  337. std::uint64_t sourceGeneration,
  338. const SenseObservationKey& key,
  339. middleware::bap::activity_message::squad_sense::State& output) noexcept;
  340. /** What the msg-5 builder needs to publish one type-65 Sense root. */
  341. struct GhostLinkLevel final {
  342. /** Generation the host last transported in the Auth body. */
  343. std::int32_t generation{};
  344. /** Client's last reported per-object counter for this slot. */
  345. std::uint32_t counter{};
  346. /** The client reported the bar at its end and the host owes it the finishing fraction. */
  347. bool finished{};
  348. };
  349. /** Copies the armed scan model for one exact type-65 slot that has reported at least once. */
  350. [[nodiscard]] bool ghost_link_scan(const state::activity::SessionBinding& binding,
  351. const SenseObservationKey& key,
  352. GhostLinkLevel& output) noexcept;
  353. /** One latest complete msg-6 object observation with values in its owning snapshot. */
  354. struct SenseObservation final {
  355. state::activity::SessionBinding binding{};
  356. SenseObservationKey key{};
  357. std::uint64_t sequence{};
  358. std::uint64_t tick{};
  359. std::uint64_t sourceGeneration{};
  360. std::uint64_t clientMessageSequence{};
  361. std::uint32_t generationPlusOne{};
  362. std::uint32_t firstValue{};
  363. std::uint32_t valueCount{};
  364. bool hasGeneration{};
  365. };
  366. /** Value-owned latest observations for one exact activity and ActivityClient generation. */
  367. struct SenseObservationSnapshot final {
  368. std::array<SenseObservation, kSenseObservationCapacity> observations{};
  369. std::array<middleware::bap::activity_message::sense_update::DecodedValue,
  370. kSenseObservationValueCapacity>
  371. values{};
  372. std::size_t observationCount{};
  373. std::size_t valueCount{};
  374. std::uint64_t revision{};
  375. std::uint64_t sourceGeneration{};
  376. };
  377. /** Exact reflected scalar identity inside one retained Sense ClientRef. */
  378. struct SenseScalarIdentity final {
  379. SenseObservationKey object{};
  380. std::uint32_t fieldSchemaRow{
  381. middleware::bap::activity_message::sense_update::kAbsentRuntimeRow};
  382. std::uint32_t fieldRow{middleware::bap::activity_message::sense_update::kAbsentRuntimeRow};
  383. std::uint32_t occurrence{};
  384. std::uint16_t fieldOrdinal{};
  385. middleware::bap::activity_message::sense_update::ValueKind kind{
  386. middleware::bap::activity_message::sense_update::ValueKind::unsignedInteger};
  387. };
  388. /** Value-owned scalar copied from one exact retained Sense observation. */
  389. struct SenseScalarSample final {
  390. state::activity::SessionBinding binding{};
  391. SenseScalarIdentity identity{};
  392. middleware::bap::activity_message::sense_update::DecodedValue value{};
  393. std::uint64_t observationRevision{};
  394. std::uint64_t tick{};
  395. std::uint64_t sourceGeneration{};
  396. std::uint64_t clientMessageSequence{};
  397. std::uint32_t generationPlusOne{};
  398. bool hasGeneration{};
  399. };
  400. /** Fail-closed result from selecting one exact scalar from a value-owned Sense snapshot. */
  401. enum class SenseScalarStatus : std::uint8_t {
  402. ready,
  403. invalidIdentity,
  404. invalidSnapshot,
  405. notFound,
  406. ambiguous,
  407. };
  408. /** Outer-valid msg-19 fields copied after envelope and exact-session ownership checks. */
  409. struct IncidentInput final {
  410. state::activity::SessionBinding binding{};
  411. middleware::bap::activity_message::incident::Incident incident{};
  412. std::uint64_t sourceGeneration{};
  413. /** Protocol ingress row for this same envelope. */
  414. std::uint64_t clientMessageSequence{};
  415. std::uint32_t payloadBytes{};
  416. middleware::bap::activity_message::player_trigger_incident::Payload playerTrigger{};
  417. middleware::bap::activity_message::cinematic_incident::Payload cinematic{};
  418. middleware::bap::activity_message::cinematic_incident::Signal cinematicSignal{
  419. middleware::bap::activity_message::cinematic_incident::Signal::started};
  420. bool hasPlayerTrigger{};
  421. bool hasCinematic{};
  422. std::uint64_t attemptGeneration{};
  423. };
  424. /** Safe msg-22 after-image submitted only after State and connection publication commit. */
  425. struct ClientStateChangeInput final {
  426. state::activity::SessionBinding binding{};
  427. state::activity::membership::CommittedClientState state{};
  428. std::uint64_t sourceGeneration{};
  429. std::uint64_t clientMessageSequence{};
  430. std::uint32_t payloadBytes{};
  431. std::uint64_t attemptGeneration{};
  432. };
  433. /** A committed msg-20 request emitted by the client's simulation-entity low-water path. */
  434. struct EntitySlotsRequestedInput final {
  435. state::activity::SessionBinding binding{};
  436. std::uint64_t sourceGeneration{};
  437. std::uint64_t clientMessageSequence{};
  438. std::int32_t requestedCount{};
  439. std::uint64_t attemptGeneration{};
  440. };
  441. /** Framing metadata copied after exact ActivityClient ownership checks. */
  442. struct ClientMessageInput final {
  443. state::activity::SessionBinding binding{};
  444. state::activity::membership::AuthoritativeUpdate authoritative{};
  445. std::uint64_t sourceGeneration{};
  446. std::uint64_t payloadFingerprint{};
  447. std::uint32_t messageType{};
  448. std::uint32_t payloadBytes{};
  449. std::uint32_t peerHeardMask{};
  450. std::uint32_t consumedBits{};
  451. ClientMessageStatus status{ClientMessageStatus::unclassified};
  452. bool hasPayloadFingerprint{};
  453. bool hasAuthoritative{};
  454. };
  455. /** One value-owned event, with no view into decrypted transport storage. */
  456. struct Event final {
  457. /** Attempt owner stamped when the native input or derived fact is admitted. */
  458. std::uint64_t attemptGeneration{};
  459. std::array<std::uint64_t, state::activity::mission::kDeviceChannelCount>
  460. deviceAppliedRequests{};
  461. state::activity::SessionBinding binding{};
  462. /** Present only for an internally synthesized timerElapsed callback. */
  463. state::activity::mission::StateKey timerName{};
  464. std::uint64_t sequence{};
  465. std::uint64_t tick{};
  466. union {
  467. std::uint64_t stateRevision{};
  468. /** Scriptable revision for scriptable output events. */
  469. std::uint64_t scriptableRevision;
  470. };
  471. std::uint64_t sourceGeneration{};
  472. /** Absolute service tick committed when the timer was armed. */
  473. std::uint64_t timerDeadlineTick{};
  474. /** Stable timer identity allocated by authoritative Mission State. */
  475. std::uint64_t timerSequence{};
  476. /** Durable intent sequence the effect call returned to the script. */
  477. std::uint64_t effectRequestKey{};
  478. /** Peer session id, for sessionJoined and sessionLeft events. */
  479. std::uint64_t peerSessionId{};
  480. /** Peer record generation, so a replacement is told apart from the record it replaced. */
  481. std::uint64_t peerSessionGeneration{};
  482. /** Peer client key bound by its join, or zero before one. */
  483. std::uint64_t peerMemberKey{};
  484. /** Party life counts, for fireteamState events. */
  485. std::uint16_t fireteamAlive{};
  486. std::uint16_t fireteamDead{};
  487. std::uint16_t fireteamUnknown{};
  488. /** Committed mission phase, for phaseEntered events. */
  489. std::uint32_t missionPhase{};
  490. /** Mission phase this commit replaced. */
  491. std::uint32_t previousMissionPhase{};
  492. /** Owning object of the slot a derived Sense edge came from. */
  493. std::uint32_t slotObjectTag{};
  494. /** Root Sense schema of the slot a derived Sense edge came from. */
  495. std::uint32_t slotSenseSchema{};
  496. /** Members of the watched set inside the volume. */
  497. std::int32_t triggerCount{};
  498. /** Member count the server asked the client to compare against. */
  499. std::int32_t triggerValue{};
  500. /** True when the whole watched set is inside the volume. */
  501. bool triggerAll{};
  502. /** For triggerState events: whether a level was reported, and the volume's occupancy. */
  503. bool triggerAvailable{}, triggerOccupied{};
  504. /** trigger_observation::Continuity of the report, for triggerState events. */
  505. std::uint8_t triggerContinuity{};
  506. /** Health and shield fractions, for damageState events. Negative until published. */
  507. float damageHealth{-1.0F};
  508. float damageShield{-1.0F};
  509. std::int32_t damageRevision{};
  510. /** Current position, power and lock levels; masks distinguish unknown fields. */
  511. std::array<float, middleware::bap::activity_message::scriptable_auth::kType23ChannelCount>
  512. deviceValues{};
  513. std::array<std::int32_t,
  514. middleware::bap::activity_message::scriptable_auth::kType23ChannelCount>
  515. deviceSequences{};
  516. std::uint8_t deviceValueMask{};
  517. std::uint8_t deviceSequenceMask{};
  518. bool deviceFirstReport{};
  519. bool deviceReset{};
  520. /** Object level, for objectState and objectInteracted events. */
  521. std::int32_t objectGeneration{};
  522. bool objectPresent{};
  523. bool objectAlive{};
  524. bool objectOwnerKnown{};
  525. bool objectHasOwner{};
  526. std::uint64_t objectOwnerKey{};
  527. /** Ghost-link level, for ghostLinkState events. */
  528. std::int32_t ghostGeneration{};
  529. float ghostProgress{};
  530. bool ghostActive{};
  531. /** Named actor level, for actorPathState events. */
  532. std::int32_t actorGeneration{};
  533. std::int32_t actorPathRevision{};
  534. std::int32_t actorPathState{};
  535. std::int32_t actorDeliveryRevision{};
  536. std::int32_t actorDeliveryState{};
  537. bool actorDeliveryKnown{};
  538. bool actorSuppressed{};
  539. /** Objective costs the squad published, one per task group, with a bit per known cost. */
  540. std::array<float, kSquadObjectiveGroupCount> squadObjectiveCosts{};
  541. std::uint32_t squadObjectiveCostMask{};
  542. std::uint32_t squadObjectiveRevision{};
  543. std::uint32_t squadObjectiveRegistryKey{};
  544. std::uint16_t squadObjectiveSlotIndex{};
  545. std::int32_t squadObjectiveTaskGroup{-1};
  546. bool squadObjectiveCostQualified{};
  547. /** Per-slot member counts the client published, for squadState events. */
  548. std::array<std::int32_t, kSquadSlotCapacity> squadSlotCounts{};
  549. /** Spawn generation the squad Sense echoes from its placement Auth; not the record counter. */
  550. std::int32_t squadSpawnGeneration{};
  551. bool squadHasSpawnGeneration{};
  552. /** The alive counts were reported; otherwise they are zero placeholders. */
  553. bool squadPopulationAvailable{};
  554. /** The report counter went backwards or the spawn generation changed: a new registration. */
  555. bool squadRegistrationReset{};
  556. /** Alive members the client published. Six bits on the wire, so 0 through 63. */
  557. std::int32_t squadAliveCount{};
  558. /** Alive count this observation replaced, for entityDied events. */
  559. std::int32_t squadPreviousAliveCount{};
  560. /** New count of the one slot that rose, for entitySpawned events. */
  561. std::int32_t squadSlotValue{};
  562. /** Count that slot held before it rose. */
  563. std::int32_t squadPreviousSlotValue{};
  564. /** Live entries in squadSlotCounts, from the list's four-bit length. */
  565. std::uint8_t squadSlotCountLength{};
  566. /** Index into squadSlotCounts that rose, for entitySpawned events. */
  567. std::uint8_t squadSlotOrdinal{};
  568. /** Client flag written on its actor death or removal path. The meaning is unproved. */
  569. bool squadRemovalFlag{};
  570. /** The removal flag was reported for this spawn lifetime. */
  571. bool squadHasRemovalFlag{};
  572. /** Msg-6 record counter plus one; not a squad or actor lifetime identity. */
  573. std::uint32_t senseGenerationPlusOne{};
  574. bool hasSenseGeneration{};
  575. /** A baseline report: it restates current levels and never proves a death. */
  576. bool initialObservation{};
  577. /** Authored entry index and spawn-mask words, for objectState events. */
  578. std::int32_t objectEntryIndex{};
  579. std::array<std::uint32_t, 2> objectSpawnMask{};
  580. /** Activation token the authored scene echoed, for sceneFinished and sceneOutput events. */
  581. std::int32_t sceneActivationToken{};
  582. /** Output gate key the scene newly reported, for sceneOutput events. */
  583. std::uint32_t sceneOutputKey{};
  584. /** Task counter the client published, for objectiveProgress events. Clamped to 80. */
  585. std::int32_t objectiveTaskCount{};
  586. /** Counter that task held before it rose. */
  587. std::int32_t objectivePreviousTaskCount{};
  588. /** Objective this task belongs to. The block is 24 long. */
  589. std::uint8_t objectiveOrdinal{};
  590. /** Task inside that objective. The list is 24 long. */
  591. std::uint8_t objectiveTaskOrdinal{};
  592. std::uint64_t clientMessageSequence{};
  593. std::uint64_t epochFirst{};
  594. std::uint64_t epochSecond{};
  595. union {
  596. std::uint64_t incidentRevision{};
  597. /** Per-binding order for client Sense/incident inputs. */
  598. std::uint64_t missionSequence;
  599. };
  600. std::uint32_t payloadBytes{};
  601. std::uint32_t peerHeardMask{};
  602. std::uint32_t tailBits{};
  603. std::uint32_t consumedBits{};
  604. std::uint32_t firstGroupBits{};
  605. union {
  606. /** First decoded registry key for Sense events. */
  607. std::uint32_t firstRegistryKey{};
  608. /** Committed region index for client-state events. */
  609. std::int32_t regionIndex;
  610. };
  611. std::uint32_t groupsSeen{};
  612. std::uint32_t groupsDecoded{};
  613. std::uint32_t groupsSkipped{};
  614. std::uint32_t objectsSeen{};
  615. std::uint32_t objectsDecoded{};
  616. union {
  617. /** Primary target for incident events. */
  618. std::uint32_t incidentTarget{};
  619. /** Associated D6 slice-set hash for client-state events. */
  620. std::uint32_t regionSliceSetHash;
  621. };
  622. /** Activity State revision from the committed msg-22 after-image. */
  623. std::uint64_t activityStateRevision{};
  624. /** The region the client holds, for client-state events whose current leg moved. */
  625. std::int32_t currentRegionIndex{-1};
  626. /**
  627. * The region the client holds after any client-state event, moved or not.
  628. * A report that moves only the pending leg still leaves the client standing where it was, and
  629. * the leg it did not restate reads absent. -1 while the client holds no region.
  630. */
  631. std::int32_t heldRegionIndex{state::activity::membership::kAbsentRegionIndex};
  632. std::int32_t previousRegionIndex{state::activity::membership::kAbsentRegionIndex};
  633. /** Membership revision from the committed msg-22 after-image. */
  634. std::uint32_t membershipRevision{};
  635. std::uint32_t teleportSliceSetHash{};
  636. std::int32_t teleportSliceSetIndex{state::activity::membership::kAbsentSliceSetIndex};
  637. std::int8_t spawnState{};
  638. std::int8_t teleportState{};
  639. std::uint32_t incidentExtraTargets{};
  640. std::uint32_t incidentSelectorBytes{};
  641. std::uint32_t incidentPayloadBytes{};
  642. /** Type-31 source ClientRef carried by a schema-0x8080879F player-trigger incident. */
  643. std::uint32_t playerTriggerRegistryKey{};
  644. std::uint32_t playerTriggerResolvedObjectId{};
  645. std::int16_t playerTriggerSlotIndex{-1};
  646. std::int8_t playerTriggerSlotType{-1};
  647. /** Type-6 source ClientRef carried by a schema-0x808087BF cinematic incident. */
  648. std::uint32_t cinematicRegistryKey{};
  649. std::uint64_t cinematicRuntimeObjectId{};
  650. float cinematicEventValue{};
  651. std::int16_t cinematicSlotIndex{-1};
  652. std::int8_t cinematicSlotType{-1};
  653. middleware::bap::activity_message::cinematic_incident::Signal cinematicSignal{
  654. middleware::bap::activity_message::cinematic_incident::Signal::started};
  655. /** Client activity-message id for clientMessageReceived events. */
  656. std::uint32_t clientMessageType{};
  657. /** Exact positive count decoded from an entitySlotsRequested msg-20 event. */
  658. std::int32_t requestedEntitySlots{};
  659. /** Safe retained scalar count for clientMessageReceived events. */
  660. std::uint16_t firstSlotIndex{};
  661. std::uint8_t firstSlotType{};
  662. std::uint8_t lifetimeState{kDefaultLifetimeState};
  663. /** Mission action kind of the requested effect, for effectResult events. */
  664. std::uint8_t effectAction{};
  665. EffectOutcome effectOutcome{EffectOutcome::transportStaged};
  666. EventKind kind{EventKind::senseUpdate};
  667. ClientMessageStatus clientMessageStatus{ClientMessageStatus::unclassified};
  668. middleware::bap::activity_message::sense_update::DecodeStatus senseDecodeStatus{
  669. middleware::bap::activity_message::sense_update::DecodeStatus::malformed};
  670. state::activity::receipts::Verdict verdict{state::activity::receipts::Verdict::absent};
  671. /** The packet's observations were retained, so a Lua snapshot may be built from them. */
  672. bool senseSnapshotRetained{};
  673. bool hasFirstObject{};
  674. bool clientStateHasRegion{};
  675. bool clientStateHasCurrentRegion{};
  676. bool clientStateHasSpawn{};
  677. bool clientStateHasTeleport{};
  678. /** The arrival answer reached the client; it spawns on that roster. */
  679. bool clientEntered{};
  680. bool hasPlayerTrigger{};
  681. bool hasCinematic{};
  682. /** @return True when this Sense event carries observations a script may read. */
  683. [[nodiscard]] bool has_sense_observations() const noexcept {
  684. using Status = middleware::bap::activity_message::sense_update::DecodeStatus;
  685. return kind == EventKind::senseUpdate && senseSnapshotRetained
  686. && (senseDecodeStatus == Status::complete || senseDecodeStatus == Status::partial);
  687. }
  688. };
  689. /** Position after one event in one reset generation. */
  690. struct EventCursor final {
  691. /** Reset generation owning sequence. */
  692. std::uint64_t generation{};
  693. std::uint64_t sequence{};
  694. };
  695. /** Value-owned result from one bounded event feed read. */
  696. struct EventRead final {
  697. std::array<Event, kEventCapacity> events{};
  698. EventCursor cursor{};
  699. std::size_t count{};
  700. /** Known events overwritten between the input cursor and the first copied row. */
  701. std::uint64_t missed{};
  702. /** At least one event in the current generation was overwritten before this read. */
  703. bool gap{};
  704. /** The input cursor named another reset generation. */
  705. bool reset{};
  706. };
  707. /** One accepted client mission input with its independent feed position. */
  708. struct MissionInputEvent final {
  709. Event event{};
  710. std::uint64_t sequence{};
  711. };
  712. /** Position after one accepted client mission input in one reset generation. */
  713. struct MissionInputCursor final {
  714. std::uint64_t generation{};
  715. std::uint64_t sequence{};
  716. };
  717. /** Value-owned accepted mission inputs after one cursor. */
  718. struct MissionInputRead final {
  719. std::array<MissionInputEvent, kMissionInputReadPageSize> events{};
  720. MissionInputCursor cursor{};
  721. std::size_t count{};
  722. /** Accepted rows between the cursor and the first retained row. */
  723. std::uint64_t missed{};
  724. /** The cursor is behind the oldest retained row. A trigger, not proof of loss. */
  725. bool gap{};
  726. bool reset{};
  727. };
  728. /** Current compact state and output status for one exact activity generation. */
  729. struct InstanceSnapshot final {
  730. state::activity::SessionBinding binding{};
  731. std::uint64_t stateRevision{};
  732. std::uint64_t transportRevision{};
  733. std::uint64_t lastEventSequence{};
  734. std::uint64_t lastOutputAttemptTick{};
  735. std::uint64_t lastOutputSourceGeneration{};
  736. std::uint64_t incidentRevision{};
  737. std::uint64_t incidentTransportRevision{};
  738. std::uint64_t scriptableRevision{};
  739. std::uint64_t scriptableTransportRevision{};
  740. std::uint64_t scriptableReservedRevision{};
  741. std::uint32_t senseCount{};
  742. std::uint32_t outputAttempts{};
  743. std::uint32_t incidentsPending{};
  744. std::uint32_t senseObservationCount{};
  745. std::uint32_t senseObservationValueCount{};
  746. std::uint64_t senseObservationRevision{};
  747. std::uint64_t senseObservationSourceGeneration{};
  748. std::uint8_t lifetimeState{kDefaultLifetimeState};
  749. OutputStatus outputStatus{OutputStatus::idle};
  750. OutputKind outputKind{OutputKind::none};
  751. bool outputPending{};
  752. bool scriptableReservationPending{};
  753. bool active{};
  754. };
  755. /** Full retained incident body and its diagnostic transport state. */
  756. struct IncidentRecord final {
  757. state::activity::SessionBinding binding{};
  758. middleware::bap::activity_message::incident::Incident incident{};
  759. std::uint64_t sequence{};
  760. std::uint64_t tick{};
  761. std::uint64_t revision{};
  762. std::uint64_t lastAttemptTick{};
  763. std::uint64_t lastSourceGeneration{};
  764. std::uint64_t clientMessageSequence{};
  765. std::uint32_t payloadBytes{};
  766. std::uint32_t attempts{};
  767. std::uint32_t transportStages{};
  768. IncidentStatus status{IncidentStatus::received};
  769. bool outbound{};
  770. };
  771. /** Compact exact generation key used by high-volume diagnostic rows. */
  772. struct ClientMessageBinding final {
  773. std::uint64_t sessionId{};
  774. std::uint64_t createdRevision{};
  775. };
  776. /** One owned client message, retained without its sensitive payload. */
  777. struct ClientMessageRecord final {
  778. ClientMessageBinding binding{};
  779. state::activity::membership::AuthoritativeUpdate authoritative{};
  780. std::uint64_t sequence{};
  781. std::uint64_t tick{};
  782. std::uint64_t sourceGeneration{};
  783. std::uint64_t payloadFingerprint{};
  784. std::uint32_t messageType{};
  785. std::uint32_t payloadBytes{};
  786. std::uint32_t peerHeardMask{};
  787. std::uint32_t consumedBits{};
  788. ClientMessageStatus status{ClientMessageStatus::unclassified};
  789. bool hasPayloadFingerprint{};
  790. bool hasAuthoritative{};
  791. };
  792. /** One typed Sense decode retained for a selected ingress row. */
  793. struct ClientMessageDetail final {
  794. middleware::bap::activity_message::sense_update::DecodedPacket sense{};
  795. std::uint64_t sequence{};
  796. std::uint32_t messageType{};
  797. bool hasSenseDecode{};
  798. };
  799. /** Value-owned protocol-message identity attached to one accepted mission-input row. */
  800. struct ClientMessageSnapshot final {
  801. std::uint32_t messageType{};
  802. ClientMessageStatus status{ClientMessageStatus::unclassified};
  803. };
  804. /** Complete immutable view copied to one UI frame. */
  805. struct DiagnosticsSnapshot final {
  806. std::array<InstanceSnapshot, kInstanceCapacity> instances{};
  807. std::array<Event, kEventCapacity> events{};
  808. std::array<IncidentRecord, kIncidentHistoryCapacity> incidents{};
  809. std::array<ClientMessageRecord, kClientMessageHistoryCapacity> clientMessages{};
  810. std::size_t instanceCount{};
  811. std::size_t eventCount{};
  812. std::size_t incidentCount{};
  813. std::size_t clientMessageCount{};
  814. std::uint64_t droppedIngress{};
  815. std::uint64_t droppedIncidents{};
  816. std::uint64_t queuedControls{};
  817. std::uint64_t refusedControls{};
  818. std::uint64_t refusedIncidents{};
  819. std::uint64_t overwrittenEvents{};
  820. std::uint64_t overwrittenIncidents{};
  821. std::uint64_t overwrittenClientMessages{};
  822. };
  823. /** Activity-state value consumed by the msg-5 output adapter. */
  824. struct AuthState final {
  825. std::uint64_t revision{};
  826. std::uint8_t lifetimeState{kDefaultLifetimeState};
  827. };
  828. /** Immutable outbound incident selected after one connection's staged revision. */
  829. struct PendingIncident final {
  830. middleware::bap::activity_message::incident::Incident incident{};
  831. std::uint64_t revision{};
  832. };
  833. /** Immutable typed body retained byte-for-byte until exact transport staging. */
  834. struct PendingScriptableOverride final {
  835. std::uint32_t actorSpawnGeneration{};
  836. /** Accepted input head when this output reached transport. */
  837. std::uint64_t missionInputSequenceAtStage{};
  838. std::uint64_t clientMessageSequenceAtStage{};
  839. bool missionInputBoundaryKnown{};
  840. state::gameplay::squad_entity_retirement::Eligibility squadRetirement{};
  841. std::array<std::byte,
  842. middleware::bap::activity_message::sensor_auth_update::kAuthOverrideByteCapacity>
  843. body{};
  844. ScriptableTarget target{};
  845. /** Exact generated group retained for a generation-bound state-local SDK request. */
  846. state::build_data::scenarios::RosterGroup stateLocalRosterGroup{};
  847. std::uint64_t revision{};
  848. std::uint64_t generation{};
  849. /** ActivityClient generation that authorized this request, or zero for unpinned input. */
  850. std::uint64_t expectedActivityClientGeneration{};
  851. std::int16_t sequence{};
  852. std::int32_t dialogueSequence{};
  853. std::uint32_t channelHash{};
  854. float channelValue{};
  855. std::uint16_t bitCount{};
  856. std::uint16_t byteCount{};
  857. std::uint16_t dialogueCue{};
  858. middleware::bap::activity_message::scriptable_auth::Type23Channel channel{};
  859. ScriptableOverrideKind kind{ScriptableOverrideKind::type23};
  860. /** Activity lifetime state for a lifetime request; ignored by every other kind. */
  861. std::uint8_t lifetimeState{kDefaultLifetimeState};
  862. bool sdkCompiled{};
  863. };
  864. /**
  865. * A burst of mission actions commits together. The head keeps every existing push behaviour and
  866. * the tail rides out with it as ordinary retained rows, so one push carries the whole burst.
  867. */
  868. inline constexpr std::size_t kPendingScriptableTailCapacity = 63;
  869. /**
  870. * Copies the committed bodies waiting on the same push as the head, oldest first.
  871. * @return Count written, never more than the output span.
  872. */
  873. [[nodiscard]] std::size_t
  874. pending_scriptable_tail(const state::activity::SessionBinding& binding,
  875. std::span<PendingScriptableOverride> output) noexcept;
  876. /** Copies one exact retained transport output for native request-to-report joins. */
  877. [[nodiscard]] bool staged_scriptable_override(const state::activity::SessionBinding& binding,
  878. std::uint64_t revision,
  879. PendingScriptableOverride& output) noexcept;
  880. /** Captures the attempt and both input heads before a publication reaches the caller. */
  881. [[nodiscard]] bool publication_input_boundary(const state::activity::SessionBinding& binding,
  882. std::uint64_t& attemptGeneration,
  883. std::uint64_t& inputSequence,
  884. std::uint64_t& clientMessageSequence) noexcept;
  885. /** Copies the latest delivered Auth body for every full ClientRef in this client generation. */
  886. [[nodiscard]] bool scriptable_auth_estate(const state::activity::SessionBinding& binding,
  887. std::uint64_t activityClientGeneration,
  888. std::vector<PendingScriptableOverride>& output) noexcept;
  889. /** Queues a native objective decision after both SDK slot identities are validated. */
  890. [[nodiscard]] bool
  891. request_squad_objective(const state::activity::SessionBinding& binding,
  892. const ScriptableTarget& target,
  893. const state::build_data::scenarios::RosterGroup* stateLocalRosterGroup,
  894. const state::activity::mission::TypedIntent& decision,
  895. std::uint16_t objectiveIndex,
  896. std::uint64_t expectedActivityClientGeneration,
  897. const ScriptableOutputReservation& reservation) noexcept;
  898. /** Names the gate that declined one ingress submission. */
  899. enum class IngressRefusal : std::uint8_t {
  900. /** The submission was queued. */
  901. none,
  902. /** The named session no longer matches a live binding. */
  903. binding,
  904. /** The submission carried no source generation to bind it to. */
  905. generation,
  906. /** The shared codec refused a bounded outer field. */
  907. payload,
  908. /** The pending-input ring held no free slot. */
  909. queue,
  910. };
  911. /**
  912. * Names the ingress gate that declined, for the skip diagnostic. Every name starts with
  913. * `host_ingress_refused`.
  914. * @param refusal Gate reported by one failed submission.
  915. * @return Stable reason name.
  916. */
  917. [[nodiscard]] const char* ingress_refusal_name(IngressRefusal refusal) noexcept;
  918. /**
  919. * Queues one owned msg-6 prefix for the Activity Host service.
  920. * @param input Owned prefix and the binding it arrived on.
  921. * @return The gate that declined, or IngressRefusal::none once queued.
  922. */
  923. [[nodiscard]] IngressRefusal submit_sense(const SenseInput& input) noexcept;
  924. /**
  925. * Queues one owned, outer-valid client msg 19 for the Activity Host service.
  926. * @param input Parsed incident and the binding it arrived on.
  927. * @return The gate that declined, or IngressRefusal::none once queued.
  928. */
  929. [[nodiscard]] IngressRefusal submit_incident(const IncidentInput& input) noexcept;
  930. /** Queues one committed client msg-22 numeric after-image for the Activity Host service. */
  931. [[nodiscard]] bool submit_client_state_change(const ClientStateChangeInput& input) noexcept;
  932. /** Queues one committed msg-20 simulation-entity slot request for the Activity Host service. */
  933. [[nodiscard]] bool submit_entity_slots_requested(const EntitySlotsRequestedInput& input) noexcept;
  934. /** Retains one owned client message without entering the reducer queue. */
  935. [[nodiscard]] std::uint64_t record_client_message(
  936. const ClientMessageInput& input,
  937. const middleware::bap::activity_message::sense_update::DecodedPacket* sense = nullptr) noexcept;
  938. /** Queues one owned client envelope that has no richer typed mission-input reducer. */
  939. [[nodiscard]] bool submit_client_message(const ClientMessageInput& input,
  940. std::uint64_t clientMessageSequence) noexcept;
  941. /** Copies one retained scalar decode by its ingress sequence. */
  942. [[nodiscard]] bool client_message_detail(std::uint64_t sequence,
  943. ClientMessageDetail& output) noexcept;
  944. /** Queues one operator Auth-state transition for the exact activity generation. */
  945. [[nodiscard]] bool request_auth_state(const state::activity::SessionBinding& binding,
  946. std::uint8_t lifetimeState) noexcept;
  947. /** Queues one outer-valid operator msg 19 for the exact activity generation. */
  948. [[nodiscard]] bool
  949. request_incident(const state::activity::SessionBinding& binding,
  950. const middleware::bap::activity_message::incident::Incident& incident) noexcept;
  951. /** Queues one generation-bound type-23 update for an exact package-derived ClientRef. */
  952. [[nodiscard]] bool
  953. request_type23_override(const state::activity::SessionBinding& binding,
  954. const ScriptableTarget& target,
  955. middleware::bap::activity_message::scriptable_auth::Type23Channel channel,
  956. float value,
  957. bool snap,
  958. std::uint64_t expectedActivityClientGeneration,
  959. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  960. /** Queues one authored object entry activation from an exact generated roster group. */
  961. [[nodiscard]] bool request_state_local_type4_override(
  962. const state::activity::SessionBinding& binding,
  963. const ScriptableTarget& target,
  964. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  965. std::int32_t entryIndex,
  966. bool active,
  967. std::uint64_t expectedActivityClientGeneration,
  968. const ScriptableOutputReservation* reservation = nullptr,
  969. const ScriptableOutputReservation* burstHead = nullptr) noexcept;
  970. /** Queues one named actor behavior-channel write from an exact generated type-2 slot. */
  971. [[nodiscard]] bool request_state_local_type2_channel_override(
  972. const state::activity::SessionBinding& binding,
  973. const ScriptableTarget& target,
  974. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  975. std::uint32_t channelHash,
  976. float value,
  977. std::uint64_t expectedActivityClientGeneration,
  978. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  979. /** Existing active sources cannot be silently repurposed by a named-actor creation. */
  980. enum class ActorProgramSourceStatus : std::uint8_t { missing, ready, incompatible };
  981. /** Reads the exact source and whether native creation may prepare it. */
  982. [[nodiscard]] ActorProgramSourceStatus
  983. actor_program_source_status(const state::activity::SessionBinding& binding,
  984. const ScriptableTarget& source,
  985. PendingScriptableOverride* output = nullptr) noexcept;
  986. /** Scene preparation must preserve an active actor owned by another binding mode. */
  987. enum class ActorSquadBindingStatus : std::uint8_t { missing, ready, incompatible };
  988. /** The SDK owns the parent relation; this query checks the transported actor binding mode. */
  989. [[nodiscard]] ActorSquadBindingStatus
  990. actor_squad_binding_status(const state::activity::SessionBinding& binding,
  991. const ScriptableTarget& actor) noexcept;
  992. /** Queues an actor program without accepting caller-owned revisions. */
  993. [[nodiscard]] bool request_type2_program(const state::activity::SessionBinding& binding,
  994. const ScriptableTarget& target,
  995. const ScriptableTarget& source,
  996. const state::build_data::scenarios::RosterGroup* group,
  997. std::span<const std::byte> body,
  998. std::uint16_t bits,
  999. bool spawn,
  1000. std::uint64_t expectedActivityClientGeneration,
  1001. const ScriptableOutputReservation* reservation = nullptr,
  1002. bool retire = false) noexcept;
  1003. /** Queues a sequence on an enabled combatant without changing its actor binding. */
  1004. [[nodiscard]] bool request_state_local_type2_sequence(
  1005. const state::activity::SessionBinding& binding,
  1006. const ScriptableTarget& target,
  1007. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1008. std::uint32_t sequenceHash,
  1009. std::uint64_t expectedActivityClientGeneration,
  1010. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1011. /** Queues squad-member binding for one exact generated type-2 combatant slot. */
  1012. [[nodiscard]] bool request_state_local_type2_squad_binding(
  1013. const state::activity::SessionBinding& binding,
  1014. const ScriptableTarget& target,
  1015. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1016. std::uint64_t expectedActivityClientGeneration,
  1017. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1018. /** Queues a generation-bound type-23 update from an exact generated roster group. */
  1019. [[nodiscard]] bool request_state_local_type23_override(
  1020. const state::activity::SessionBinding& binding,
  1021. const ScriptableTarget& target,
  1022. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1023. middleware::bap::activity_message::scriptable_auth::Type23Channel channel,
  1024. float value,
  1025. bool snap,
  1026. std::uint64_t expectedActivityClientGeneration,
  1027. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1028. /** Queues one type-31 arm, or a disarm, for an exact package-derived ClientRef. */
  1029. [[nodiscard]] bool request_type31_override(const state::activity::SessionBinding& binding,
  1030. const ScriptableTarget& target,
  1031. const ScriptableOutputReservation* reservation = nullptr,
  1032. bool enabled = true) noexcept;
  1033. /** Queues one type-31 pulse carried by the exact generated group in the current activity seed. */
  1034. [[nodiscard]] bool request_state_local_type31_override(
  1035. const state::activity::SessionBinding& binding,
  1036. const ScriptableTarget& target,
  1037. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1038. std::uint64_t expectedActivityClientGeneration,
  1039. const ScriptableOutputReservation* reservation = nullptr,
  1040. bool enabled = true) noexcept;
  1041. /** Queues one authored sequence restart from the exact generated mission group. */
  1042. [[nodiscard]] bool request_state_local_sequence_override(
  1043. const state::activity::SessionBinding& binding,
  1044. const ScriptableTarget& target,
  1045. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1046. std::uint64_t expectedActivityClientGeneration,
  1047. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1048. /** Queues one authored cinematic start or stop from the exact generated mission group. */
  1049. [[nodiscard]] bool request_state_local_cinematic_override(
  1050. const state::activity::SessionBinding& binding,
  1051. const ScriptableTarget& target,
  1052. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1053. bool active,
  1054. std::uint64_t expectedActivityClientGeneration,
  1055. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1056. /** Queues one type-42 performance start naming a state of the sensor's target actor. */
  1057. [[nodiscard]] bool request_state_local_performance_override(
  1058. const state::activity::SessionBinding& binding,
  1059. const ScriptableTarget& target,
  1060. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1061. std::uint32_t stateNameHash,
  1062. std::uint64_t expectedActivityClientGeneration,
  1063. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1064. /** Queues one full objective reset from the exact generated group in the mission seed. */
  1065. [[nodiscard]] bool request_state_local_objective_reset(
  1066. const state::activity::SessionBinding& binding,
  1067. const ScriptableTarget& target,
  1068. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1069. std::uint64_t expectedActivityClientGeneration,
  1070. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1071. /** Queues one authored-task generation from the exact generated group in the mission seed. */
  1072. [[nodiscard]] bool request_state_local_task_override(
  1073. const state::activity::SessionBinding& binding,
  1074. const ScriptableTarget& target,
  1075. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1076. std::uint64_t expectedActivityClientGeneration,
  1077. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1078. /** Queues one authored-scene activation from the exact generated group in the mission seed. */
  1079. [[nodiscard]] bool request_state_local_authored_scene_override(
  1080. const state::activity::SessionBinding& binding,
  1081. const ScriptableTarget& target,
  1082. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1083. std::uint64_t expectedActivityClientGeneration,
  1084. const ScriptableOutputReservation* reservation = nullptr,
  1085. const AuthoredSceneDependencies& dependencies = {},
  1086. std::uint32_t eventKey = 0,
  1087. bool stop = false) noexcept;
  1088. /** Queues one authored dialogue line from the exact generated group in the mission seed. */
  1089. [[nodiscard]] bool request_state_local_dialogue_override(
  1090. const state::activity::SessionBinding& binding,
  1091. const ScriptableTarget& target,
  1092. const state::build_data::scenarios::RosterGroup& stateLocalRosterGroup,
  1093. std::uint16_t cueIndex,
  1094. std::uint16_t authoredCueCount,
  1095. std::uint64_t expectedActivityClientGeneration,
  1096. const ScriptableOutputReservation* reservation = nullptr,
  1097. middleware::bap::activity_message::scriptable_auth::Type2LaneClientRef filter = {}) noexcept;
  1098. /** Queues one squad placement intent for an exact package-derived ClientRef. */
  1099. [[nodiscard]] bool request_squad_override(
  1100. const state::activity::SessionBinding& binding,
  1101. const ScriptableTarget& target,
  1102. const state::build_data::scenarios::RosterGroup* stateLocalRosterGroup,
  1103. std::span<const std::int32_t> requestedCounts,
  1104. middleware::bap::activity_message::squad_auth::Mode mode,
  1105. std::uint64_t expectedActivityClientGeneration,
  1106. std::optional<std::uint32_t> nameHash = std::nullopt,
  1107. const ScriptableOutputReservation* reservation = nullptr,
  1108. std::array<std::int8_t, 4> authoredProfile = {},
  1109. state::gameplay::squad_entity_retirement::Eligibility squadRetirement = {},
  1110. std::optional<middleware::bap::activity_message::squad_auth::Destination> destination =
  1111. std::nullopt,
  1112. std::optional<middleware::bap::activity_message::squad_auth::SpawnRule> spawnRule =
  1113. std::nullopt) noexcept;
  1114. /** Queues one generation-bound activity lifetime state through the serialized output slot. */
  1115. [[nodiscard]] bool
  1116. request_lifetime_override(const state::activity::SessionBinding& binding,
  1117. std::uint8_t lifetimeState,
  1118. std::uint64_t expectedActivityClientGeneration,
  1119. const ScriptableOutputReservation* reservation = nullptr) noexcept;
  1120. /** Queues one exact SDK-compiled Auth body for a generation-bound ClientRef. */
  1121. [[nodiscard]] bool
  1122. request_sdk_auth_override(const state::activity::SessionBinding& binding,
  1123. const ScriptableTarget& target,
  1124. const state::build_data::scenarios::RosterGroup* stateLocalRosterGroup,
  1125. std::span<const std::byte> body,
  1126. std::uint16_t bitCount,
  1127. std::uint64_t expectedActivityClientGeneration,
  1128. const ScriptableOutputReservation* reservation = nullptr,
  1129. ScriptableOverrideKind kind = ScriptableOverrideKind::sdkAuth) noexcept;
  1130. /** @return True while any live instance holds a committed output the transport has not sent. */
  1131. [[nodiscard]] bool any_output_pending() noexcept;
  1132. /** Holds one exact next scriptable revision without queueing or exposing an output body. */
  1133. [[nodiscard]] bool reserve_scriptable_output(const state::activity::SessionBinding& binding,
  1134. ScriptableOutputReservation& output,
  1135. std::uint64_t intentSequence = 0) noexcept;
  1136. /** Releases only the exact unarmed reservation returned by reserve_scriptable_output. */
  1137. [[nodiscard]] bool
  1138. release_scriptable_output(const ScriptableOutputReservation& reservation) noexcept;
  1139. /**
  1140. * Atomically withdraws an exact queued Mission reducer row or reports its committed disposition.
  1141. * A caller may release durable State ownership only after `withdrawn`, `absent`, or `canceled`.
  1142. */
  1143. [[nodiscard]] ScriptableWithdrawStatus
  1144. withdraw_scriptable_output(const state::activity::SessionBinding& binding,
  1145. std::uint64_t intentSequence,
  1146. std::uint64_t expectedRevision) noexcept;
  1147. /** Applies queued client and operator events on the server service slice. */
  1148. void service(std::uint64_t now) noexcept;
  1149. /** Copies the latest complete diagnostic view. */
  1150. void snapshot(DiagnosticsSnapshot& output) noexcept;
  1151. /** Copies one exact activity generation without exposing the Host lock. */
  1152. [[nodiscard]] bool instance_snapshot(const state::activity::SessionBinding& binding,
  1153. InstanceSnapshot& output) noexcept;
  1154. /** Reads the current feed position without replaying retained history. */
  1155. [[nodiscard]] EventCursor current_event_cursor() noexcept;
  1156. /**
  1157. * Copies retained events after one cursor and advances output.cursor to the newest row.
  1158. * A zero cursor returns retained rows and reports reset against the live generation.
  1159. */
  1160. void read_events_after(EventCursor after, EventRead& output) noexcept;
  1161. /** Reads the current accepted-mission-input position without replaying retained history. */
  1162. [[nodiscard]] MissionInputCursor current_mission_input_cursor() noexcept;
  1163. /**
  1164. * Copies accepted client mission inputs after one cursor.
  1165. * A row is dropped only once durable mission State no longer owes it. A read is not a commit.
  1166. */
  1167. void read_mission_inputs_after(MissionInputCursor after, MissionInputRead& output) noexcept;
  1168. /** Copies the exact Sense values owned by one retained accepted-input row. */
  1169. [[nodiscard]] bool mission_input_sense_snapshot(std::uint64_t sequence,
  1170. SenseObservationSnapshot& output) noexcept;
  1171. /** Copies the safe generic values owned by one retained accepted-input row. */
  1172. [[nodiscard]] bool mission_input_client_message_snapshot(std::uint64_t sequence,
  1173. ClientMessageSnapshot& output) noexcept;
  1174. /** Copies the latest complete Sense observations for one exact activity generation. */
  1175. [[nodiscard]] bool snapshot_sense_observations(const state::activity::SessionBinding& binding,
  1176. SenseObservationSnapshot& output) noexcept;
  1177. /** Selects one exact reflected scalar without changing the retained snapshot. */
  1178. [[nodiscard]] SenseScalarStatus select_sense_scalar(const SenseObservationSnapshot& snapshot,
  1179. const state::activity::SessionBinding& binding,
  1180. const SenseScalarIdentity& identity,
  1181. SenseScalarSample& output) noexcept;
  1182. /** @return True when two selected scalars have the same presence and raw typed value. */
  1183. [[nodiscard]] bool same_sense_scalar_value(const SenseScalarSample& left,
  1184. const SenseScalarSample& right) noexcept;
  1185. /** @return True when both samples name the same ActivityClient and reported object generations. */
  1186. [[nodiscard]] bool same_sense_scalar_generations(const SenseScalarSample& left,
  1187. const SenseScalarSample& right) noexcept;
  1188. /** @return Stable text for one exact scalar-selection result. */
  1189. [[nodiscard]] const char* sense_scalar_status_name(SenseScalarStatus status) noexcept;
  1190. /** Reads the committed Auth state for one exact activity generation. */
  1191. [[nodiscard]] bool auth_state(const state::activity::SessionBinding& binding,
  1192. AuthState& output) noexcept;
  1193. /** Reads the one pending incident occupying the exact instance's serialized output slot. */
  1194. [[nodiscard]] bool pending_incident(const state::activity::SessionBinding& binding,
  1195. PendingIncident& output) noexcept;
  1196. /** Reads the one pending typed ClientRef body without changing its counter. */
  1197. [[nodiscard]] bool pending_scriptable_override(const state::activity::SessionBinding& binding,
  1198. PendingScriptableOverride& output) noexcept;
  1199. /**
  1200. * Reads an override for one exact ActivityClient generation.
  1201. * A state-local request authorized by another generation is atomically canceled here.
  1202. */
  1203. [[nodiscard]] bool
  1204. pending_scriptable_override_for_activity_client(const state::activity::SessionBinding& binding,
  1205. std::uint64_t activityClientGeneration,
  1206. PendingScriptableOverride& output) noexcept;
  1207. /** Cancels the exact instance's raw incident before any later transport staging. */
  1208. [[nodiscard]] bool cancel_pending_incident(const state::activity::SessionBinding& binding) noexcept;
  1209. /** Cancels one exact unstaged typed override revision without advancing its slot counter. */
  1210. [[nodiscard]] bool
  1211. cancel_pending_scriptable_override(const state::activity::SessionBinding& binding,
  1212. std::uint64_t expectedRevision) noexcept;
  1213. /** Records one refused BAP attempt without clearing the committed output. */
  1214. void note_auth_attempt(const state::activity::SessionBinding& binding,
  1215. std::uint64_t sourceGeneration,
  1216. std::uint64_t revision,
  1217. std::uint8_t lifetimeState,
  1218. OutputStatus status) noexcept;
  1219. /** Marks one committed Auth revision as staged into the transport output queue. */
  1220. void note_auth_transport_staged(const state::activity::SessionBinding& binding,
  1221. std::uint64_t sourceGeneration,
  1222. std::uint64_t revision,
  1223. std::uint8_t lifetimeState) noexcept;
  1224. /** Records one failed attempt without advancing a connection's incident cursor. */
  1225. void note_incident_attempt(const state::activity::SessionBinding& binding,
  1226. std::uint64_t sourceGeneration,
  1227. std::uint64_t revision,
  1228. IncidentStatus status) noexcept;
  1229. /** Marks one retained incident revision as staged into a matching transport output queue. */
  1230. void note_incident_transport_staged(const state::activity::SessionBinding& binding,
  1231. std::uint64_t sourceGeneration,
  1232. std::uint64_t revision) noexcept;
  1233. /** Records one refused typed-body attempt without consuming its sequence or generation. */
  1234. void note_scriptable_attempt(const state::activity::SessionBinding& binding,
  1235. std::uint64_t sourceGeneration,
  1236. const PendingScriptableOverride& pending,
  1237. OutputStatus status) noexcept;
  1238. /** Commits one exact typed body and only then advances its full-slot counter. */
  1239. void note_scriptable_transport_staged(const state::activity::SessionBinding& binding,
  1240. std::uint64_t sourceGeneration,
  1241. const PendingScriptableOverride& pending) noexcept;
  1242. /** Clears every instance, queue, and diagnostic counter. */
  1243. void reset() noexcept;
  1244. /** @return Stable UI name for one event kind. */
  1245. [[nodiscard]] const char* event_name(EventKind kind) noexcept;
  1246. /** @return Stable UI name for one framing verdict. */
  1247. [[nodiscard]] const char* verdict_name(state::activity::receipts::Verdict verdict) noexcept;
  1248. /** @return Stable UI name for one output attempt status. */
  1249. [[nodiscard]] const char* output_status_name(OutputStatus status) noexcept;
  1250. /** @return Stable UI name for one retained incident status. */
  1251. [[nodiscard]] const char* incident_status_name(IncidentStatus status) noexcept;
  1252. /** @return Stable diagnostic name for one client message type. */
  1253. [[nodiscard]] const char* client_message_name(std::uint32_t messageType) noexcept;
  1254. /** @return Stable diagnostic name for one client body status. */
  1255. [[nodiscard]] const char* client_message_status_name(ClientMessageStatus status) noexcept;
  1256. } // namespace sunrise::server::activity::host