internal.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. #pragma once
  2. #include <array>
  3. #include <bitset>
  4. #include <cstddef>
  5. #include <cstdint>
  6. #include <span>
  7. #include <vector>
  8. #include "../../../../core/filesystem/path.h"
  9. #include "../../../../middleware/content/packages/reader/reader.h"
  10. #include "../../../../middleware/content/packages/tables/definition_index_table.h"
  11. #include "../../../../middleware/content/packages/tables/items.h"
  12. #include "../../../../state/build_data/abilities/definition.h"
  13. #include "../../../../state/build_data/collectibles/collectible_catalog.h"
  14. #include "../../../../state/build_data/constants/definition.h"
  15. #include "../../../../state/build_data/inventory/buckets/definition.h"
  16. #include "../../../../state/build_data/items/details/definition.h"
  17. #include "../../../../state/build_data/items/item_catalog.h"
  18. #include "../../../../state/build_data/material_requirements/material_requirement_catalog.h"
  19. #include "../../../../state/build_data/progressions/definition.h"
  20. #include "../../../../state/build_data/runtime.h"
  21. namespace sunrise::client::content::items::packages {
  22. namespace reader = middleware::content::packages::reader;
  23. namespace tables = middleware::content::packages::tables;
  24. /** Equippable rows, their initial plugs, and authored override plugs. */
  25. inline constexpr std::size_t kDetailCapacity =
  26. state::build_data::items::details::kDefinitionCapacity;
  27. /** Native item indices selected for the deduplicated detail closure. */
  28. using DetailRequests = std::bitset<state::build_data::items::kDefinitionCapacity>;
  29. /** Authored definition hashes one pass looks for while walking the item index table. */
  30. struct AuthoredHashes {
  31. std::array<std::uint32_t, kDetailCapacity> values{};
  32. std::size_t count{};
  33. };
  34. /** Everything the detail pass needs to read one requested definition from the packages. */
  35. struct DetailSource {
  36. const reader::Source* source{};
  37. reader::Scratch* scratch{};
  38. /** Item index table blob owning the located array. */
  39. std::span<const std::byte> table{};
  40. tables::Array array{};
  41. std::vector<std::byte>* definition{};
  42. };
  43. /** The container name is not always unique, so every match is a candidate. */
  44. inline constexpr std::size_t kContainerCandidates = 16;
  45. /** Lock-owned storage kept off the caller stack, shared by every stage of the pass. */
  46. struct Storage {
  47. reader::Scratch scratch{};
  48. std::vector<std::byte> container{};
  49. std::vector<std::byte> child{};
  50. std::vector<std::byte> root{};
  51. std::vector<std::byte> definition{};
  52. /** Shared reusable/randomized plug-set table read from investment-root slot 51. */
  53. std::vector<std::byte> plugSetTable{};
  54. /** Compact 0..3 special plug-category code of every dense installed item row. */
  55. std::array<std::uint8_t, state::build_data::items::kDefinitionCapacity> specialPlugCategories{};
  56. /** Inventory routing rows held until the paired bucket-definition table is resolved. */
  57. std::array<state::build_data::inventory::buckets::Descriptor,
  58. state::build_data::inventory::buckets::kDescriptorCapacity>
  59. bucketRows{};
  60. std::size_t bucketCount{};
  61. std::array<std::int8_t, state::build_data::inventory::buckets::kDescriptorCapacity>
  62. equipmentSlotByBucket{};
  63. DetailRequests detailRequests{};
  64. std::array<std::uint16_t, kDetailCapacity> requestedDetailIndices{};
  65. std::vector<state::build_data::items::details::Definition> details{};
  66. AuthoredHashes authoredHashes{};
  67. std::vector<std::byte> abilityTable{};
  68. std::vector<std::byte> abilityPool{};
  69. std::array<state::build_data::abilities::Definition,
  70. state::build_data::abilities::kDefinitionCapacity>
  71. abilityRows{};
  72. std::array<state::build_data::progressions::Definition,
  73. state::build_data::progressions::kDefinitionCapacity>
  74. progressionRows{};
  75. std::array<state::build_data::collectibles::Definition,
  76. state::build_data::collectibles::kDefinitionCapacity>
  77. collectibleRows{};
  78. std::array<state::build_data::material_requirements::Definition,
  79. state::build_data::material_requirements::kDefinitionCapacity>
  80. materialRequirementRows{};
  81. std::array<state::build_data::items::Definition, state::build_data::items::kDefinitionCapacity>
  82. rows{};
  83. };
  84. /**
  85. * Collects the authored equipment and plug hashes every configured character names.
  86. * Hashes are sorted so the index-table walk can test each row by binary search instead of
  87. * rescanning the whole authored set per row.
  88. * @param output Receives the sorted unique authored hashes.
  89. * @return True when the account is good and every hash fits.
  90. */
  91. [[nodiscard]] bool collect_authored_hashes(AuthoredHashes& output) noexcept;
  92. /** @param hashes Sorted authored hashes. @param hash Row hash. @return True when authored. */
  93. [[nodiscard]] bool authored(const AuthoredHashes& hashes, std::uint32_t hash) noexcept;
  94. /**
  95. * @param row Installed item row.
  96. * @return True when its bucket maps to an equipment slot
  97. * supported by the generated loadout.
  98. */
  99. [[nodiscard]] bool equippable(const tables::items::Row& row) noexcept;
  100. /** Publishes parsed inventory buckets after applying the extracted item-slot relation. */
  101. [[nodiscard]] bool publish_buckets(Storage& storage) noexcept;
  102. /**
  103. * Adds one definition index to the deduplicated requested set.
  104. * @param definitionIndex Native
  105. * item index.
  106. * @param requested Requested-set storage.
  107. */
  108. void request(std::uint16_t definitionIndex, DetailRequests& requested) noexcept;
  109. /**
  110. * Adds every socket lane's initial plug to the requested set.
  111. * A lane using native defaults falls back to this plug, so its detail must exist.
  112. * @param row
  113. * Item row already read from its definition blob.
  114. * @param itemDefinitionCount Installed
  115. * item-table bound.
  116. * @param requested Requested-set storage.
  117. */
  118. void append_initial_plugs(const tables::items::Row& row,
  119. std::uint64_t itemDefinitionCount,
  120. DetailRequests& requested) noexcept;
  121. /**
  122. * Materializes requested native indices in ascending order.
  123. * @param requested Deduplicated
  124. * native-index set.
  125. * @param output Fixed detail-index storage.
  126. * @param count Receives the
  127. * number of selected rows, or zero when output is too small.
  128. * @return True when every selected
  129. * row fits.
  130. */
  131. [[nodiscard]] bool materialize_requests(const DetailRequests& requested,
  132. std::span<std::uint16_t> output,
  133. std::size_t& count) noexcept;
  134. /**
  135. * Reads one requested definition and turns it into its cached detail form.
  136. * @param source Located item index table and package reader state.
  137. * @param definitionIndex Native item index.
  138. * @param detail Receives the cached detail.
  139. * @param item Receives the raw definition row the detail was built from.
  140. * @return True when the row is found and its definition blob reads.
  141. */
  142. [[nodiscard]] bool build_detail(const DetailSource& source,
  143. std::uint16_t definitionIndex,
  144. state::build_data::items::details::Definition& detail,
  145. tables::items::Row& item) noexcept;
  146. /**
  147. * Reads the stat rows the installed investment constants blob names.
  148. * @param source Package source.
  149. * @param scratch Reader scratch.
  150. * @param root Investment root bytes.
  151. * @param blob Scratch storage for the constants blob.
  152. * @param output Receives the extracted stat rows.
  153. * @return True when the blob reads and carries every named row.
  154. */
  155. [[nodiscard]] bool
  156. read_investment_constants(const reader::Source& source,
  157. reader::Scratch& scratch,
  158. std::span<const std::byte> root,
  159. std::vector<std::byte>& blob,
  160. state::build_data::constants::InvestmentConstants& output) noexcept;
  161. /**
  162. * Builds the ability buckets one subclass publishes under one ability selection.
  163. * @param source Package source.
  164. * @param scratch Reader scratch.
  165. * @param listDefinition Socket-entry-list definition bytes of the subclass.
  166. * @param blob Scratch storage reused for every pool blob.
  167. * @param selection The character's 5 selected socket entries.
  168. * @param output Receives the 12 buckets and the overflow bank.
  169. * @return True when every selected entry reaches a bucket of its own.
  170. */
  171. [[nodiscard]] bool build_ability_buckets(const reader::Source& source,
  172. reader::Scratch& scratch,
  173. std::span<const std::byte> listDefinition,
  174. std::vector<std::byte>& blob,
  175. const state::build_data::abilities::Selection& selection,
  176. state::build_data::abilities::Definition& output) noexcept;
  177. /**
  178. * Builds one ability bucket row per distinct subclass and ability selection in use.
  179. * Two characters on the same subclass with the same ability selection publish identical
  180. * buckets, so the row is keyed by both and built once.
  181. * @param source Package source.
  182. * @param scratch Reader scratch.
  183. * @param root Investment root bytes.
  184. * @param table Scratch storage for the socket entry list table.
  185. * @param definition Scratch storage for one socket entry list definition.
  186. * @param blob Scratch storage reused for every pool blob.
  187. * @param output Row storage.
  188. * @param count Receives the number of rows built.
  189. * @return True when the table reads; a subclass that fails is skipped, not fatal.
  190. */
  191. [[nodiscard]] bool
  192. build_character_abilities(const reader::Source& source,
  193. reader::Scratch& scratch,
  194. std::span<const std::byte> root,
  195. std::vector<std::byte>& table,
  196. std::vector<std::byte>& definition,
  197. std::vector<std::byte>& blob,
  198. std::span<state::build_data::abilities::Definition> output,
  199. std::size_t& count) noexcept;
  200. /**
  201. * Reads the progression definition table and the object array each definition routes to.
  202. * The table is inline rows, not index rows. The scope byte in a row picks the replicated object
  203. * holding that progression, and the row's place among rows of that scope is its slot there.
  204. * @param source Package source.
  205. * @param scratch Reader scratch.
  206. * @param root Investment root bytes.
  207. * @param blob Scratch storage for the table.
  208. * @param output Row storage in native definition order.
  209. * @param count Receives the number of rows read.
  210. * @return True when the table reads and every row fits.
  211. */
  212. [[nodiscard]] bool build_progressions(const reader::Source& source,
  213. reader::Scratch& scratch,
  214. std::span<const std::byte> root,
  215. std::vector<std::byte>& blob,
  216. std::span<state::build_data::progressions::Definition> output,
  217. std::size_t& count) noexcept;
  218. /**
  219. * Copies the block key material this pass borrows.
  220. * @param keys Receives the primary, alternate and nonce material.
  221. * @return True when the installed key table and the bootstrap token are both there.
  222. */
  223. [[nodiscard]] bool collect_keys(reader::BlockKeys& keys) noexcept;
  224. /**
  225. * Collects every catalogue tag carrying the container name.
  226. * @param candidates Receives the candidate tags.
  227. * @param count Receives the number of candidates.
  228. * @return True when the catalogue names at least one.
  229. */
  230. [[nodiscard]] bool
  231. investment_globals_tags(std::array<std::uint32_t, kContainerCandidates>& candidates,
  232. std::size_t& count) noexcept;
  233. /** @param directory Receives the installed packages directory. @return True when it exists. */
  234. [[nodiscard]] bool package_directory(core::path::Buffer& directory) noexcept;
  235. /** @param slot Requested-set position. @param definitionIndex Native item index that failed. */
  236. void report_detail_failure(std::size_t slot, std::uint16_t definitionIndex) noexcept;
  237. /** @param count Ability bucket rows the pass built, one per subclass and ability selection. */
  238. void report_ability_count(std::size_t count) noexcept;
  239. /** Reports a bounded number of exact subclass/ability extraction failures per process. */
  240. void report_ability_failure(const char* stage,
  241. std::size_t character,
  242. std::size_t first,
  243. std::size_t second) noexcept;
  244. /** Reports requested, retained, and skipped detail closure rows. */
  245. void report_detail_count(std::size_t requested, std::size_t built) noexcept;
  246. /**
  247. * Reports the item index-table walk, including rows the pass could not read.
  248. * @param walked Table entries the pass visited.
  249. * @param rows Readable rows it retained.
  250. * @param skipped Entries omitted because their index row or definition was malformed.
  251. * @param truncated True when the walk stopped early because the row storage filled.
  252. */
  253. void report_row_count(std::size_t walked,
  254. std::size_t rows,
  255. std::size_t skipped,
  256. bool truncated) noexcept;
  257. /** Reports the exact socket-rule, deduplicated-pool, member, and skipped-lane counts. */
  258. void report_socket_plug_count(std::size_t rules,
  259. std::size_t pools,
  260. std::size_t members,
  261. std::size_t skipped) noexcept;
  262. /** Reports the validated installed bucket/equipment-slot coverage. */
  263. void report_bucket_equipment_mapping(std::size_t mappedSlots) noexcept;
  264. /** Reports the first rejected bucket-definition invariant in one process. */
  265. void report_bucket_equipment_failure(const char* stage,
  266. std::size_t first,
  267. std::size_t second) noexcept;
  268. /**
  269. * Reports the pass outcome once.
  270. * @param published Rows published, or zero on failure.
  271. * @param reason Stage the pass reached, named in the line.
  272. */
  273. void report(std::size_t published, const char* reason) noexcept;
  274. /**
  275. * Publishes the inventory bucket descriptors from the root's bucket table.
  276. * @param source Package source.
  277. * @param storage Pass storage.
  278. * @param root Investment root bytes.
  279. * @return True when the table reads and publishes.
  280. */
  281. [[nodiscard]] bool build_buckets(const reader::Source& source,
  282. Storage& storage,
  283. std::span<const std::byte> root) noexcept;
  284. /**
  285. * Publishes the socket entry list table from the root.
  286. * @param source Package source.
  287. * @param storage Pass storage.
  288. * @param root Investment root bytes.
  289. * @return True when the table reads and publishes.
  290. */
  291. [[nodiscard]] bool build_socket_entry_lists(const reader::Source& source,
  292. Storage& storage,
  293. std::span<const std::byte> root) noexcept;
  294. /**
  295. * Reads and publishes the root's dense collectible-to-item mapping table.
  296. * @param source
  297. * Package source.
  298. * @param storage Pass storage, including scratch bytes and bounded row storage.
  299. * * @param root Investment root bytes.
  300. * @param itemDefinitionCount Number of rows in the
  301. * installed item index table.
  302. * @return True when every tag, class, bound, and item link validates
  303. * and publishes.
  304. */
  305. [[nodiscard]] bool build_collectibles(const reader::Source& source,
  306. Storage& storage,
  307. std::span<const std::byte> root,
  308. std::uint64_t itemDefinitionCount) noexcept;
  309. /**
  310. * Walks the located item index table, then publishes every domain that depends on it.
  311. * @param source Package source.
  312. * @param storage Pass storage holding the located table blob.
  313. * @param table Located item index array.
  314. * @param rowCount Receives the dense item rows published.
  315. * @param reason Receives the step name when a stage fails.
  316. * @return True when the dense table and every dependent domain publish.
  317. */
  318. [[nodiscard]] bool build_item_rows(const reader::Source& source,
  319. Storage& storage,
  320. const tables::Array& table,
  321. std::size_t& rowCount,
  322. const char*& reason) noexcept;
  323. /** Reads and publishes every native material-requirement set from investment-root slot 96. */
  324. [[nodiscard]] bool build_material_requirements(const reader::Source& source,
  325. Storage& storage,
  326. std::span<const std::byte> root,
  327. std::uint64_t itemDefinitionCount) noexcept;
  328. } // namespace sunrise::client::content::items::packages