host_runtime.h 55 KB

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