runtime.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. #pragma once
  2. #include <array>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <span>
  6. #include "state.h"
  7. namespace sunrise::state::account::settings {
  8. struct SettingsDelta;
  9. } // namespace sunrise::state::account::settings
  10. namespace sunrise::state {
  11. /**
  12. * Assigns runtime SOIDs only to installed profile mod/shader rows which are socket action sources.
  13. * Currency, material, and consumable profile rows remain canonically non-instanced.
  14. */
  15. [[nodiscard]] bool ensure_profile_item_identities() noexcept;
  16. /**
  17. * Grants each character the other 2 subclasses of its equipped subclass's class, placing missing
  18. * ones into unequipped inventory with native socket defaults. Idempotent: one already equipped or
  19. * already in inventory is left alone.
  20. * @return True when every such character holds its whole class, or there was nothing to check.
  21. */
  22. [[nodiscard]] bool ensure_character_subclasses() noexcept;
  23. /** Prepared subclass socket-entry selection for the equipped selected-character subclass. */
  24. struct PendingSubclassSelection {
  25. /** Exact prepare-time character view used as the commit staleness guard. */
  26. CharacterState beforeCharacter{};
  27. /** Canonical after-image. Only one authored ability-entry field differs. */
  28. CharacterState afterCharacter{};
  29. std::uint64_t accountSoid{};
  30. std::uint64_t characterSoid{};
  31. std::uint64_t subclassInstanceSoid{};
  32. std::uint32_t subclassDefinitionHash{};
  33. std::size_t characterIndex{};
  34. std::uint16_t subclassDefinitionIndex{};
  35. std::uint16_t socketEntryListIndex{};
  36. /** Exact entry named by opcode 801. */
  37. std::uint8_t requestedEntry{};
  38. bool prepared{};
  39. };
  40. /**
  41. * Prepares one opcode-801 selection against the selected character's exact equipped subclass.
  42. * The installed socket-entry table maps the request to whichever of the character's 5 authored
  43. * picks competes in the same group; no class-specific node indices are authored in State.
  44. */
  45. [[nodiscard]] bool prepare_subclass_selection(std::uint64_t subclassInstanceSoid,
  46. std::uint8_t requestedEntry,
  47. PendingSubclassSelection& mutation) noexcept;
  48. /** Produces the complete uncommitted account after-image for a prepared subclass selection. */
  49. [[nodiscard]] bool preview_subclass_selection(const PendingSubclassSelection& mutation,
  50. AccountState& after) noexcept;
  51. /** Commits a prepared subclass selection behind the exact full-character staleness guard. */
  52. [[nodiscard]] bool commit_subclass_selection(PendingSubclassSelection& mutation) noexcept;
  53. /** Direction of one checked character equipment mutation. */
  54. enum class EquipmentMutationKind : std::uint8_t {
  55. none,
  56. equip,
  57. unequip,
  58. };
  59. /** Prepared character-inventory mutation kept private until its response and update both fit. */
  60. struct PendingEquipmentSwap {
  61. /** Exact prepare-time character view used as the commit staleness guard. */
  62. CharacterState beforeCharacter{};
  63. /** Canonical after-image, including every row-change mutation generation. */
  64. CharacterState afterCharacter{};
  65. std::uint64_t characterSoid{};
  66. std::uint64_t requestedInstanceSoid{};
  67. std::uint64_t previousInstanceSoid{};
  68. std::size_t characterIndex{};
  69. std::size_t equipmentSlotIndex{};
  70. std::size_t inventoryIndex{};
  71. std::size_t movedItemCount{};
  72. std::uint8_t nativeEquipmentSlot{};
  73. EquipmentMutationKind kind{};
  74. bool prepared{};
  75. };
  76. /** Prepared selected-character inventory insertion kept private until its reply and push fit. */
  77. struct PendingItemAcquisition {
  78. CharacterState beforeCharacter{};
  79. CharacterState afterCharacter{};
  80. /** Profile material view, before and after charging the native requirement set. */
  81. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  82. beforeProfileItems{};
  83. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  84. afterProfileItems{};
  85. std::uint64_t accountSoid{};
  86. std::uint64_t characterSoid{};
  87. std::uint64_t acquiredInstanceSoid{};
  88. std::uint32_t acquiredDefinitionHash{};
  89. std::uint32_t materialRequirementSetHash{};
  90. std::uint32_t expectedNextInventorySerial{};
  91. std::size_t characterIndex{};
  92. std::size_t expectedInventoryCount{};
  93. std::size_t expectedProfileItemCount{};
  94. std::size_t afterProfileItemCount{};
  95. std::size_t inventoryIndex{};
  96. std::uint16_t collectibleIndex{};
  97. std::uint16_t inventoryRow{};
  98. std::uint8_t equipmentSlot{};
  99. std::uint8_t materialRequirementCount{};
  100. bool profileChanged{};
  101. bool prepared{};
  102. };
  103. /** Prepared account-profile stack insertion kept private until its reply and account upsert fit. */
  104. struct PendingProfileItemAcquisition {
  105. /** Exact profile inventory observed while preparing the mutation. */
  106. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  107. beforeItems{};
  108. /** Canonical profile inventory after incrementing or appending one stack. */
  109. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  110. afterItems{};
  111. std::uint64_t accountSoid{};
  112. /** Stable profile-row source identity, preserved for increments and allocated for appends. */
  113. std::uint64_t acquiredInstanceSoid{};
  114. std::uint32_t acquiredDefinitionHash{};
  115. std::uint32_t materialRequirementSetHash{};
  116. std::size_t expectedItemCount{};
  117. std::size_t afterItemCount{};
  118. std::size_t profileIndex{};
  119. std::int32_t previousQuantity{};
  120. std::int32_t acquiredQuantity{};
  121. std::int32_t previousMutationSerial{};
  122. std::int32_t acquiredMutationSerial{};
  123. std::uint16_t collectibleIndex{};
  124. std::uint8_t bucketId{};
  125. std::uint8_t materialRequirementCount{};
  126. /** True only for installed profile mod/shader rows materialized as Family-4 residents. */
  127. bool actionSource{};
  128. bool appended{};
  129. bool prepared{};
  130. };
  131. /** One profile material actually credited by a prepared dismantle. */
  132. struct DismantleReward {
  133. std::uint32_t definitionHash{};
  134. std::size_t profileIndex{};
  135. std::int32_t quantity{};
  136. std::int32_t afterQuantity{};
  137. std::int32_t mutationSerial{};
  138. };
  139. /** Dismantle feedback can publish every bounded server-authored policy row. */
  140. inline constexpr std::size_t kDismantleRewardCapacity = kDismantleRewardPolicyCapacity;
  141. /** Prepared selected-character inventory removal kept private until its reply and push fit. */
  142. struct PendingItemDismantle {
  143. /** Exact prepare-time character view used as the commit staleness guard. */
  144. CharacterState beforeCharacter{};
  145. /** Canonical dense inventory after-image, including row-change mutation generations. */
  146. CharacterState afterCharacter{};
  147. /** Exact profile material view observed before and after applying the dismantle payout. */
  148. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  149. beforeProfileItems{};
  150. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  151. afterProfileItems{};
  152. std::array<DismantleReward, kDismantleRewardCapacity> rewards{};
  153. account::inventory::Item dismantledItem{};
  154. std::uint64_t accountSoid{};
  155. std::uint64_t characterSoid{};
  156. std::uint64_t dismantledInstanceSoid{};
  157. std::size_t characterIndex{};
  158. std::size_t expectedInventoryCount{};
  159. std::size_t expectedProfileItemCount{};
  160. std::size_t afterProfileItemCount{};
  161. std::size_t inventoryIndex{};
  162. std::size_t movedInventoryItemCount{};
  163. std::size_t rewardCount{};
  164. std::uint16_t inventoryRow{};
  165. std::uint8_t equipmentSlot{};
  166. bool profileChanged{};
  167. bool prepared{};
  168. };
  169. /** Prepared ordinary-socket selection for one selected-character item instance. */
  170. struct PendingSocketPlug {
  171. /** Exact prepare-time character view used as the commit staleness guard. */
  172. CharacterState beforeCharacter{};
  173. /** Canonical after-image. Only the target item's authored socket block differs. */
  174. CharacterState afterCharacter{};
  175. /** Exact account-wide material balances observed before applying the installed cost set. */
  176. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  177. beforeProfileItems{};
  178. /** Canonical material balances after every consuming row in the installed cost set. */
  179. std::array<account::inventory::ProfileItem, account::inventory::kProfileItemCapacity>
  180. afterProfileItems{};
  181. std::uint64_t accountSoid{};
  182. std::uint64_t characterSoid{};
  183. std::uint64_t targetInstanceSoid{};
  184. std::uint32_t targetDefinitionHash{};
  185. std::uint32_t plugDefinitionHash{};
  186. std::uint32_t materialRequirementSetHash{};
  187. std::size_t characterIndex{};
  188. std::size_t expectedProfileItemCount{};
  189. std::size_t afterProfileItemCount{};
  190. /** Equipment semantic index or dense inventory index, selected by `targetEquipped`. */
  191. std::size_t itemIndex{};
  192. std::uint16_t targetDefinitionIndex{};
  193. /** Plug that lands in the lane. Differs from the request only for a rolled socket. */
  194. std::uint16_t plugDefinitionIndex{};
  195. /** Plug the Client asked for, which decides the pool check and the material charge. */
  196. std::uint16_t requestedPlugDefinitionIndex{};
  197. std::uint16_t materialRequirementSetIndex{0xFFFFU};
  198. std::uint8_t socketLane{};
  199. std::uint8_t targetBucketId{};
  200. std::uint8_t plugBucketId{};
  201. std::uint8_t materialRequirementCount{};
  202. bool profileChanged{};
  203. bool targetEquipped{};
  204. bool prepared{};
  205. };
  206. /** Prepared accumulated item-state change for one selected-character item instance. */
  207. struct PendingItemState {
  208. CharacterState beforeCharacter{};
  209. CharacterState afterCharacter{};
  210. std::uint64_t characterSoid{};
  211. std::uint64_t targetInstanceSoid{};
  212. std::size_t characterIndex{};
  213. /** Equipment semantic index or dense inventory index, selected by `targetEquipped`. */
  214. std::size_t itemIndex{};
  215. std::uint16_t targetDefinitionIndex{};
  216. std::uint32_t beforeFlags{};
  217. std::uint32_t afterFlags{};
  218. bool targetEquipped{};
  219. bool prepared{};
  220. };
  221. /** Prepared current-activity change for the selected character, private until it publishes. */
  222. struct PendingCurrentActivity {
  223. CharacterState beforeCharacter{};
  224. CharacterState afterCharacter{};
  225. std::uint64_t characterSoid{};
  226. std::size_t characterIndex{};
  227. std::uint16_t activityIndex{};
  228. bool prepared{};
  229. };
  230. /** Result of validating one sparse settings writeback against authoritative State. */
  231. enum class SettingsUpdateDisposition : std::uint8_t {
  232. rejected,
  233. acceptedNoChange,
  234. preparedMutation,
  235. };
  236. /** Complete checked settings before/after images held until the BAP transaction commits. */
  237. struct PendingSettingsUpdate {
  238. account::settings::AccountSettings beforeSettings{};
  239. account::settings::AccountSettings afterSettings{};
  240. std::uint64_t accountSoid{};
  241. bool prepared{};
  242. };
  243. /**
  244. * Loads cached build data and generates secrets with Sunrise's authored activity defaults.
  245. * @param module Loaded Sunrise module, or null to disable disk persistence.
  246. * @param initialAccount Empty State, or a complete checked account from Core settings.
  247. * @return True when the cached data passes its checks and every secret is generated.
  248. */
  249. [[nodiscard]] bool initialize(void* module = nullptr,
  250. const AccountState& initialAccount = {}) noexcept;
  251. /**
  252. * Loads cached build data and publishes fixed activity defaults in one step.
  253. * @param module Loaded Sunrise module, or null to disable disk persistence.
  254. * @param initialAccount Empty State, or a complete checked account from Core settings.
  255. * @param activityDefaults Complete local fallback policy from immutable Core settings.
  256. * @return True when account, defaults, cached data, and generated secrets are valid.
  257. */
  258. [[nodiscard]] bool
  259. initialize(void* module,
  260. const AccountState& initialAccount,
  261. const activity::defaults::ActivityDefaults& activityDefaults) noexcept;
  262. /** Securely clears State, including activity destinations and matchmaking descriptors. */
  263. void shutdown() noexcept;
  264. /** @return Immutable generated SignOn session fields. */
  265. [[nodiscard]] const SignOnState& sign_on() noexcept;
  266. [[nodiscard]] bool publish_bootstrap_token(std::span<const std::byte> token) noexcept;
  267. /**
  268. * Records when the account signed in.
  269. * Every character record publishes this as its last applied daily and weekly reset.
  270. * @param seconds Unix seconds taken when the SignOn success is answered.
  271. */
  272. void publish_sign_in_time(std::uint64_t seconds) noexcept;
  273. /** @return Immutable generated BAP session fields. */
  274. [[nodiscard]] const BapState& bap() noexcept;
  275. /**
  276. * Generates one connection's own secure-channel material.
  277. * Two links sharing a key and a starting nonce would encrypt different plaintexts under the same
  278. * pair, so every accepted connection gets its own.
  279. * @param output Cleared, then filled with a fresh nonce, session key and envelope IV.
  280. * @return True when the system generated every byte.
  281. */
  282. [[nodiscard]] bool new_bap_session(BapState& output) noexcept;
  283. /**
  284. * Stores the active nonzero account key when the account remains complete.
  285. * @param primarySoid Account key selected by the local Client.
  286. * @return False when the key or resulting account State is invalid.
  287. */
  288. [[nodiscard]] bool set_primary_soid(std::uint64_t primarySoid) noexcept;
  289. /**
  290. * Moves the selection to one authored character.
  291. * The Client names its pick only in the select-character request, so this is where a player's
  292. * choice enters State.
  293. * @param characterSoid Picked character key, which must name an authored character.
  294. * @param changed Receives whether the selection moved to a different character.
  295. * @return False when no authored character carries that key.
  296. */
  297. [[nodiscard]] bool set_selected_character(std::uint64_t characterSoid, bool& changed) noexcept;
  298. /**
  299. * Prepares an equip operation for one unequipped instance on the selected character.
  300. * An occupied slot is swapped; an empty semantic slot receives the requested item directly.
  301. * @param requestedInstanceSoid Unequipped item instance selected by the Client.
  302. * @param mutation Gets the checked after-image without changing account State.
  303. * @return True when the instance is owned, unequipped, and maps to one native equipment slot.
  304. */
  305. [[nodiscard]] bool prepare_equipment_swap(std::uint64_t requestedInstanceSoid,
  306. PendingEquipmentSwap& mutation) noexcept;
  307. /**
  308. * Prepares an unequip operation for one equipped selected-character instance.
  309. * The item is inserted before existing inventory items in its native bucket so their published
  310. * rows remain stable. Native slots without a proven semantic State mapping are rejected.
  311. *
  312. * @param requestedInstanceSoid Equipped item instance selected by the Client.
  313. * @param mutation Gets the checked after-image without changing account State.
  314. * @return True when the instance is equipped and the dense character inventory has room.
  315. */
  316. [[nodiscard]] bool prepare_equipment_unequip(std::uint64_t requestedInstanceSoid,
  317. PendingEquipmentSwap& mutation) noexcept;
  318. /**
  319. * Commits a prepared equipment mutation only while the full captured character still matches.
  320. *
  321. * @param mutation Prepared mutation, always cleared before this function returns.
  322. * @return True when the equip or unequip commits atomically and leaves the account valid.
  323. */
  324. [[nodiscard]] bool commit_equipment_swap(PendingEquipmentSwap& mutation) noexcept;
  325. /**
  326. * Prepares one installed equippable definition as a new selected-character inventory instance.
  327. *
  328. * Native-default sockets, a unique runtime SOID, and the selected character's current item level
  329. * are used. Full loadout resolution is the authoritative bucket-capacity check.
  330. *
  331. * @param collectibleIndex Collections row the Client pulled from.
  332. * @param definitionHash Installed item definition requested by the Client.
  333. * @param mutation Gets a checked after-image without changing account State.
  334. * @return True when the item and every existing loadout row resolve with one free native row.
  335. */
  336. [[nodiscard]] bool prepare_item_acquisition(std::uint16_t collectibleIndex,
  337. std::uint32_t definitionHash,
  338. PendingItemAcquisition& mutation) noexcept;
  339. /** Builds the exact full-account after-image while a prepared item pull remains current. */
  340. [[nodiscard]] bool preview_item_acquisition(const PendingItemAcquisition& mutation,
  341. AccountState& after) noexcept;
  342. /**
  343. * Commits a prepared inventory insertion only while its selected character, existing loadout,
  344. * and next inventory serial still match the prepare-time view.
  345. *
  346. * @param mutation Prepared mutation, always cleared before this function returns.
  347. * @return True when the insertion commits atomically and leaves the whole account valid.
  348. */
  349. [[nodiscard]] bool commit_item_acquisition(PendingItemAcquisition& mutation) noexcept;
  350. /**
  351. * Prepares one installed profile-owned stackable definition for a Collections pull.
  352. *
  353. * An existing non-full stack is incremented. Otherwise a new dense State entry is appended only
  354. * when the installed profile bucket still owns a free native row.
  355. *
  356. * @param collectibleIndex Collections row the Client pulled from.
  357. * @param definitionHash Installed stackable definition requested by the Client.
  358. * @param mutation Gets the checked profile before/after images without changing account State.
  359. * @return True when the definition belongs to the main profile array and one unit fits.
  360. */
  361. [[nodiscard]] bool
  362. prepare_profile_item_acquisition(std::uint16_t collectibleIndex,
  363. std::uint32_t definitionHash,
  364. PendingProfileItemAcquisition& mutation) noexcept;
  365. /**
  366. * Materializes a prepared profile acquisition over the current account only while its complete
  367. * profile-inventory view is unchanged. This is the account object encoded before commit.
  368. *
  369. * @param mutation Prepared mutation that remains owned by the transaction.
  370. * @param after Gets the exact full-account after-image used by the Family-4 upsert.
  371. * @return True when the mutation is whole and its prepare-time profile remains current.
  372. */
  373. [[nodiscard]] bool preview_profile_item_acquisition(const PendingProfileItemAcquisition& mutation,
  374. AccountState& after) noexcept;
  375. /**
  376. * Commits a prepared profile stack insertion only while its prepare-time profile remains current.
  377. *
  378. * @param mutation Prepared mutation, always cleared before this function returns.
  379. * @return True when the stack update commits atomically and leaves the whole account valid.
  380. */
  381. [[nodiscard]] bool
  382. commit_profile_item_acquisition(PendingProfileItemAcquisition& mutation) noexcept;
  383. /**
  384. * Prepares removal of one unequipped instance from the selected character.
  385. * The authored inventory prefix is compacted. Any surviving item whose installed native row
  386. * changes receives a fresh mutation generation. Equipped items are never accepted.
  387. * @param instanceSoid Unequipped item-instance key selected by the Client.
  388. * @param mutation Gets checked before/after images without changing account State.
  389. * @return True when the selected character uniquely owns it and both loadouts resolve.
  390. */
  391. [[nodiscard]] bool prepare_item_dismantle(std::uint64_t instanceSoid,
  392. PendingItemDismantle& mutation) noexcept;
  393. /** Builds the exact account after-image while a prepared dismantle remains current. */
  394. [[nodiscard]] bool preview_item_dismantle(const PendingItemDismantle& mutation,
  395. AccountState& after) noexcept;
  396. /**
  397. * Commits a prepared inventory removal only while the complete prepare-time character view is
  398. * unchanged.
  399. *
  400. * @param mutation Prepared mutation, always cleared before this function returns.
  401. * @return True when the removal commits atomically and leaves the whole account valid.
  402. */
  403. [[nodiscard]] bool commit_item_dismantle(PendingItemDismantle& mutation) noexcept;
  404. /**
  405. * Prepares one exact opcode-903 ordinary-socket selection on a selected-character item.
  406. * The target may be equipped or unequipped. Native defaults are materialized into a complete
  407. * authored socket block, then only the requested lane changes; everything else stays byte-stable.
  408. * @param targetInstanceSoid Selected-character item-instance key named by the Client.
  409. * @param socketLane Zero-based ordinary socket lane.
  410. * @param plugDefinitionIndex Installed plug-definition row selected by the Client.
  411. * @param mutation Gets the checked before/after images without changing account State.
  412. * @return True when ownership, item detail, lane, plug compatibility, and both loadouts validate.
  413. */
  414. [[nodiscard]] bool prepare_socket_plug(std::uint64_t targetInstanceSoid,
  415. std::uint8_t socketLane,
  416. std::uint16_t plugDefinitionIndex,
  417. PendingSocketPlug& mutation) noexcept;
  418. /**
  419. * Prepares one ordinary-socket selection for an exact character-screen item selector.
  420. * The resolved instance runs through the same checked transition as an instance-addressed action,
  421. * so acquired and unequipped items do not depend on a coincidental menu-row ordinal.
  422. * @param instanceIdentityToken Item-instance identity decoded from the opcode-1901 selector.
  423. * @param requestedSocketLane Native socket action lane; compatibility resolves the physical lane.
  424. * @param plugDefinitionIndex Installed plug-definition row selected by the Client.
  425. * @param mutation Gets the checked before/after images without changing account State.
  426. * @return True when one item matches, the plug resolves to that lane, and the transition is valid.
  427. */
  428. [[nodiscard]] bool prepare_character_selector_socket_plug(std::uint64_t instanceIdentityToken,
  429. std::uint8_t requestedSocketLane,
  430. std::uint16_t plugDefinitionIndex,
  431. PendingSocketPlug& mutation) noexcept;
  432. /** Produces the complete uncommitted account after-image for a prepared socket transaction. */
  433. [[nodiscard]] bool preview_socket_plug(const PendingSocketPlug& mutation,
  434. AccountState& after) noexcept;
  435. /**
  436. * Commits a prepared socket selection only while the complete prepare-time character is unchanged.
  437. * @param mutation Prepared mutation, always cleared before this function returns.
  438. * @return True when the exact canonical transition commits atomically.
  439. */
  440. [[nodiscard]] bool commit_socket_plug(PendingSocketPlug& mutation) noexcept;
  441. /** Prepares one complete native item-state value for an owned selected-character instance. */
  442. [[nodiscard]] bool prepare_item_state(std::uint64_t targetInstanceSoid,
  443. std::uint16_t targetDefinitionIndex,
  444. std::uint32_t flags,
  445. PendingItemState& mutation) noexcept;
  446. /** Commits one prepared item-state change behind an exact full-character staleness guard. */
  447. [[nodiscard]] bool commit_item_state(PendingItemState& mutation) noexcept;
  448. /**
  449. * Prepares the selected character's current activity, family-4 `+45896`, without changing State.
  450. * @param activityIndex Activity the character is launching into.
  451. * @param mutation Gets the checked after-image.
  452. * @return True when a character is selected and the value changes.
  453. */
  454. [[nodiscard]] bool prepare_current_activity(std::uint16_t activityIndex,
  455. PendingCurrentActivity& mutation) noexcept;
  456. /** Commits one prepared current-activity change behind an exact character staleness guard. */
  457. [[nodiscard]] bool commit_current_activity(PendingCurrentActivity& mutation) noexcept;
  458. /**
  459. * Merges and validates a sparse WS-701 settings update without publishing it.
  460. * @param delta Supported fields decoded from one reflected settings request.
  461. * @param mutation Receives a complete before/after pair only when State would change.
  462. * @return Rejection, an accepted no-op, or a prepared mutation.
  463. */
  464. [[nodiscard]] SettingsUpdateDisposition
  465. prepare_settings_update(const account::settings::SettingsDelta& delta,
  466. PendingSettingsUpdate& mutation) noexcept;
  467. /**
  468. * Publishes one prepared settings after-image behind account-key and settings staleness guards.
  469. * @param mutation Prepared update, always cleared before this function returns.
  470. * @return True when the after-image was already current or was committed successfully.
  471. */
  472. [[nodiscard]] bool commit_settings_update(PendingSettingsUpdate& mutation) noexcept;
  473. /** @return A copy of the active account state, read under the lock. */
  474. [[nodiscard]] AccountState account_snapshot() noexcept;
  475. /**
  476. * Copies the evaluated content state and adds build-derived catalyst completion overrides.
  477. * @param output Receives one complete Family-5 snapshot on success.
  478. * @return False when the fixed override banks cannot hold the complete state.
  479. */
  480. [[nodiscard]] bool investment_snapshot(InvestmentState& output) noexcept;
  481. } // namespace sunrise::state