internal.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #pragma once
  2. #include <optional>
  3. #include <span>
  4. #include "../../../../../middleware/datagen/family4/loadout/definition.h"
  5. #include "../../../../../middleware/datagen/family4/loadout/loadout_resolver.h"
  6. #include "../../../../../state/account/account_state.h"
  7. #include "../../../../../state/build_data/definition.h"
  8. #include "../../../../../state/equipment/light/definition.h"
  9. #include "snapshot.h"
  10. #include "snapshot_storage.h"
  11. namespace sunrise::server::bap::encrypted::push::snapshot {
  12. /** Initial family snapshots start at version zero. */
  13. inline constexpr std::int32_t kInitialFamilyVersion = 0;
  14. /** Family three carries the account roster selected by Web Service subscription. */
  15. inline constexpr std::uint32_t kRosterFamilyType = 3;
  16. /** Family four carries account and selected-character investment state. */
  17. inline constexpr std::uint32_t kAccountFamilyType = 4;
  18. /** Descriptor slot zero owns the family-three account roster object. */
  19. inline constexpr std::uint32_t kRosterDefinitionSlotIndex = 0;
  20. /** Descriptor slot zero owns the family-four account object. */
  21. inline constexpr std::uint32_t kAccountDefinitionSlotIndex = 0;
  22. /** Descriptor slot one owns the family-four selected-character object. */
  23. inline constexpr std::uint32_t kCharacterDefinitionSlotIndex = 1;
  24. /** Descriptor slot three supplies the schema shared by every family-four item instance. */
  25. inline constexpr std::uint32_t kItemDefinitionSlotIndex = 3;
  26. /** Prepared descriptor zero carries the family-four account object. */
  27. inline constexpr std::size_t kAccountObjectIndex = 0;
  28. /** Prepared descriptor one carries the selected family-four character object. */
  29. inline constexpr std::size_t kCharacterObjectIndex = 1;
  30. /** Prepared item descriptors start after the account and selected-character descriptors. */
  31. inline constexpr std::size_t kFirstItemObjectIndex = kFamily4IdentityObjectCount;
  32. /**
  33. * Prepared item descriptors start here when no character is selected.
  34. * Item records cover every character in the roster, so they go out with or without a selection.
  35. * The account object is then the only descriptor ahead of them.
  36. */
  37. inline constexpr std::size_t kFirstItemObjectIndexUnselected = kAccountObjectIndex + 1;
  38. /** Pins feed-referenced item identities to their published character rows. */
  39. [[nodiscard]] bool apply_acquisition_presentation(
  40. std::span<std::byte> characterBytes,
  41. const middleware::datagen::family4::loadout::ResolvedLoadout& loadout,
  42. std::span<const queuez::AcquisitionPresentationRow> presentationRows) noexcept;
  43. /**
  44. * Builds the family-three account roster snapshot.
  45. * @param scratch Object storage owned by the lock.
  46. * @param subscription Family id the Client picked.
  47. * @param objectId Id the roster object publishes under.
  48. * @param reservation Prior payload prefixes that staging must keep.
  49. * @param prepared Gets the roster descriptor and the scratch clear extent.
  50. * @return True when State and the mapped object size fit.
  51. */
  52. [[nodiscard]] bool prepare_roster(Scratch& scratch,
  53. const middleware::queuez::Subscription& subscription,
  54. std::uint32_t objectId,
  55. const Reservation& reservation,
  56. Prepared& prepared) noexcept;
  57. /**
  58. * Compresses one encoded family-four object into the next sealed scratch segment.
  59. * @param scratch Raw and compressed snapshot storage owned by the lock.
  60. * @param encoded The encoded object bytes, in the raw scratch prefix.
  61. * @param definitionId Descriptor id mapped at runtime.
  62. * @param version Object SOID, used as the first object version.
  63. * @param destinationOffset First unused byte of compressed scratch.
  64. * @param object Gets a descriptor only after compression works.
  65. * @param written Gets the compressed size in bytes.
  66. * @return True when the whole stream fits the remaining sealed storage.
  67. */
  68. [[nodiscard]] bool compress_object(Scratch& scratch,
  69. std::span<const std::byte> encoded,
  70. std::uint32_t definitionId,
  71. std::uint64_t version,
  72. std::size_t destinationOffset,
  73. middleware::queuez::Object& object,
  74. std::size_t& written) noexcept;
  75. /**
  76. * Builds the Family-4 account, selected-character, and item-instance snapshot.
  77. * @param scratch Object and compression storage owned by the lock.
  78. * @param subscription Family id the Client picked.
  79. * @param accountObjectId Id the account object publishes under.
  80. * @param reservation Prior payload prefixes that staging must keep.
  81. * @param prepared Gets the compressed object descriptors and scratch clear extents.
  82. * @return True when State, mappings, layouts and the installed compression all fit.
  83. */
  84. [[nodiscard]] bool
  85. prepare(Scratch& scratch,
  86. const middleware::queuez::Subscription& subscription,
  87. std::uint32_t accountObjectId,
  88. const Reservation& reservation,
  89. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  90. Prepared& prepared) noexcept;
  91. /**
  92. * Builds the Family-4 increment that moves the character object to the picked character.
  93. * @param scratch Object and compression storage owned by the lock.
  94. * @param select Checked after-image, object definitions and both character keys.
  95. * @param prepared Gets the release and both upsert descriptors.
  96. * @return True when State, mappings, layouts and the installed compression all fit.
  97. */
  98. [[nodiscard]] bool prepare_selection_move(Scratch& scratch,
  99. const queuez::SelectCharacter& select,
  100. Prepared& prepared) noexcept;
  101. /**
  102. * Builds the Family-4 character upsert for one prepared equipment swap.
  103. * @param scratch Object and compression storage owned by the lock.
  104. * @param swap Checked queuez version after-image and resident character definition.
  105. * @param mutation Checked State after-image that is not committed yet.
  106. * @param acquisitionPresentationRows Item identities pinned to feed-referenced rows.
  107. * @param prepared Gets the single character upsert descriptor.
  108. * @return True when the after-image encodes and the complete object fits.
  109. */
  110. [[nodiscard]] bool prepare_equipment_swap(
  111. Scratch& scratch,
  112. const queuez::EquipmentSwap& swap,
  113. const state::PendingEquipmentSwap& mutation,
  114. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  115. Prepared& prepared) noexcept;
  116. /** Builds the Family-4 character upsert carrying one accumulated item-state change. */
  117. [[nodiscard]] bool
  118. prepare_item_state(Scratch& scratch,
  119. const queuez::EquipmentSwap& update,
  120. const state::PendingItemState& mutation,
  121. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  122. Prepared& prepared) noexcept;
  123. /**
  124. * Builds the Family-4 item-instance upsert for one prepared ordinary-socket selection.
  125. * The character object is unchanged because item identity, placement and mutation generation are
  126. * preserved; the socket block lives entirely in the resident instance object.
  127. */
  128. [[nodiscard]] bool prepare_socket_plug(Scratch& scratch,
  129. const queuez::SocketPlug& socketPlug,
  130. const state::PendingSocketPlug& mutation,
  131. Prepared& prepared) noexcept;
  132. /** Builds the Family-4 subclass item-instance upsert for one prepared node selection. */
  133. [[nodiscard]] bool prepare_subclass_selection(Scratch& scratch,
  134. const queuez::SubclassSelection& selection,
  135. const state::PendingSubclassSelection& mutation,
  136. Prepared& prepared) noexcept;
  137. /**
  138. * Builds one Family-4 increment containing the newly resident item object followed by the
  139. * changed character that references it.
  140. * @param scratch Object and compression storage owned by the lock.
  141. * @param acquisition Exact queuez after-image promised by the correlated response.
  142. * @param mutation Checked State after-image that remains uncommitted while output is staged.
  143. * @param prepared Gets the two upsert descriptors in item-then-character dependency order.
  144. * @return True when both after-image objects encode and fit atomically.
  145. */
  146. [[nodiscard]] bool prepare_item_acquisition(
  147. Scratch& scratch,
  148. const queuez::ItemAcquisition& acquisition,
  149. const state::PendingItemAcquisition& mutation,
  150. std::optional<std::uint16_t> pendingSeasonReward,
  151. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  152. Prepared& prepared) noexcept;
  153. /**
  154. * Builds one Family-4 increment containing the full account after-image for a profile stack.
  155. *
  156. * No resident is added: the account root is upserted at the exact staged +1 revision.
  157. */
  158. [[nodiscard]] bool
  159. prepare_profile_item_acquisition(Scratch& scratch,
  160. const queuez::ProfileItemAcquisition& acquisition,
  161. const state::PendingProfileItemAcquisition& mutation,
  162. std::optional<std::uint16_t> pendingSeasonReward,
  163. Prepared& prepared) noexcept;
  164. /** Builds a transient XP inventory-row acquisition and the account progression after-image. */
  165. [[nodiscard]] bool prepare_seasonal_experience_presentation(
  166. Scratch& scratch,
  167. const queuez::SessionState& before,
  168. std::int32_t amount,
  169. std::int32_t mutationSerial,
  170. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  171. Prepared& prepared) noexcept;
  172. /** Builds one package increment containing its new instances, character, and account objects. */
  173. [[nodiscard]] bool prepare_season_pass_package(
  174. Scratch& scratch,
  175. const queuez::SessionState& before,
  176. const state::PendingDirectItemBundle& mutation,
  177. std::uint16_t rewardIndex,
  178. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  179. Prepared& prepared) noexcept;
  180. /** Builds one atomic record-reward batch in resident, character, account order. */
  181. [[nodiscard]] bool prepare_record_reward_grant(
  182. Scratch& scratch,
  183. const queuez::SessionState& before,
  184. const queuez::RecordRewardGrant& update,
  185. const state::PendingRecordRewardGrant& mutation,
  186. std::span<const queuez::AcquisitionPresentationRow> acquisitionPresentationRows,
  187. Prepared& prepared) noexcept;
  188. /**
  189. * Builds one Family-4 increment containing the changed character and released item instance.
  190. * @param scratch Object and compression storage owned by the lock.
  191. * @param dismantle Exact queuez after-image promised by the correlated response.
  192. * @param mutation Checked State after-image that remains uncommitted while output is staged.
  193. * @param prepared Gets the character upsert followed by the empty release descriptor.
  194. * @return True when the character after-image and two-operation update fit atomically.
  195. */
  196. [[nodiscard]] bool prepare_item_dismantle(Scratch& scratch,
  197. const queuez::ItemDismantle& dismantle,
  198. const state::PendingItemDismantle& mutation,
  199. Prepared& prepared) noexcept;
  200. /** Selected-character mappings the character and item-instance encoders need. */
  201. struct Resolved {
  202. std::size_t characterIndex{};
  203. middleware::datagen::family4::loadout::ResolvedLoadout loadout{};
  204. state::equipment::light::Evaluation lightEvaluation{};
  205. std::uint32_t characterObjectId{};
  206. std::uint32_t itemInstanceObjectId{};
  207. };
  208. /**
  209. * Finds the selected character row inside one validated account snapshot.
  210. * @param account Account State read under the lock.
  211. * @return Row index, or no value when nothing is selected.
  212. */
  213. [[nodiscard]] std::optional<std::size_t>
  214. find_character_index(const state::AccountState& account) noexcept;
  215. /**
  216. * Finds one selected row plus its character schema and, if items exist, the instance schema.
  217. * @param account Validated account State read under the lock.
  218. * @param characterIndex Selected row in the used part of the character array.
  219. * @param output Gets the mappings only after every lookup works.
  220. * @return True when the loadout and queuez mappings fit the encoder ABIs.
  221. */
  222. [[nodiscard]] bool
  223. resolve(const state::AccountState& account, std::size_t characterIndex, Resolved& output) noexcept;
  224. /** Logs which step of preparation failed. @return Always false. */
  225. [[nodiscard]] bool report_failure(const char* step) noexcept;
  226. /**
  227. * Compresses one raw object and advances the shared sealed-buffer extent.
  228. * @param scratch Raw and compressed storage owned by the lock.
  229. * @param encoded The raw object bytes.
  230. * @param definitionId Descriptor id mapped at runtime.
  231. * @param version Object SOID, used as its first version.
  232. * @param object Gets the finished object descriptor.
  233. * @param compressedExtent First unused sealed byte, advanced on success.
  234. * @return True when the object fits the remaining sealed storage.
  235. */
  236. [[nodiscard]] bool append_object(Scratch& scratch,
  237. std::span<const std::byte> encoded,
  238. std::uint32_t definitionId,
  239. std::uint64_t version,
  240. middleware::queuez::Object& object,
  241. std::size_t& compressedExtent) noexcept;
  242. /**
  243. * Encodes and appends one character's row-sorted item instances after any already staged.
  244. * @param scratch Raw and compressed storage owned by the lock.
  245. * @param rawStorage Writable raw staging tail after any prior live payload.
  246. * @param itemInstanceObjectId Id each item object publishes under.
  247. * @param instances Every found item instance for one character.
  248. * @param baseIndex First descriptor slot the items may use. It shifts with whether the
  249. * selected-character descriptor sits ahead of them.
  250. * @param staged Prepared snapshot that takes the item descriptors from the base index on.
  251. * @param itemCursor Item descriptors already staged, advanced for every item.
  252. * @param compressedExtent First unused sealed byte, advanced for every item.
  253. * @return True when every item encodes and compresses with nothing half-published.
  254. */
  255. [[nodiscard]] bool
  256. append_items(Scratch& scratch,
  257. std::span<std::byte> rawStorage,
  258. std::uint32_t itemInstanceObjectId,
  259. const middleware::datagen::family4::loadout::ResolvedInstances& instances,
  260. std::size_t baseIndex,
  261. Prepared& staged,
  262. std::size_t& itemCursor,
  263. std::size_t& compressedExtent) noexcept;
  264. /** Resolves one source-backed profile stack into the shared Family-4 item-instance schema. */
  265. [[nodiscard]] bool resolve_profile_item_instance(
  266. const state::account::inventory::ProfileItem& profileItem,
  267. middleware::datagen::family4::instance::ResolvedInstance& output) noexcept;
  268. /**
  269. * Appends every source-backed profile item after all character-owned item residents.
  270. * Native
  271. * currency/material/consumable rows have zero SOIDs and intentionally add no descriptor.
  272. */
  273. [[nodiscard]] bool append_profile_items(Scratch& scratch,
  274. std::span<std::byte> rawStorage,
  275. std::uint32_t itemInstanceObjectId,
  276. const state::AccountState& account,
  277. std::size_t baseIndex,
  278. Prepared& staged,
  279. std::size_t& itemCursor,
  280. std::size_t& compressedExtent) noexcept;
  281. } // namespace sunrise::server::bap::encrypted::push::snapshot