internal.h 14 KB

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