activity_sdk_pack_composer_rows.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. #include <array>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <limits>
  5. #include <string_view>
  6. #include "activity_sdk_activity_inventory.h"
  7. #include "activity_sdk_actor_rsat_inventory.h"
  8. #include "activity_sdk_authored_scene_inventory.h"
  9. #include "activity_sdk_behavior_inventory.h"
  10. #include "activity_sdk_pack_composer_internal.h"
  11. #include "activity_sdk_policy_inventory.h"
  12. #include "activity_sdk_squad_inventory.h"
  13. #include "activity_sdk_topology_enrichment.h"
  14. #include "activity_sdk_topology_inventory.h"
  15. namespace sunrise::client::content::activity::sdk_generation::pack_composer {
  16. namespace {
  17. /** Format-v9 state rows use bits zero and one for enabled and extraction-complete state. */
  18. constexpr std::uint32_t kStateEnabled = 0x1U;
  19. constexpr std::uint32_t kStateExtractionComplete = 0x2U;
  20. static_assert((kStateEnabled | kStateExtractionComplete) == format::kStateFlagMask);
  21. template <typename Text>
  22. [[nodiscard]] bool text_view(const Text& input, std::string_view& output) noexcept {
  23. output = {};
  24. if (input.length >= input.value.size() || input.value[input.length] != '\0') {
  25. return false;
  26. }
  27. output = {input.value.data(), input.length};
  28. return true;
  29. }
  30. [[nodiscard]] bool policy_text_view(const policy_inventory::Snapshot& source,
  31. policy_inventory::Text input,
  32. std::string_view& output) noexcept {
  33. output = {};
  34. if (input.stringIndex >= source.strings.size()) {
  35. return false;
  36. }
  37. output = source.strings[input.stringIndex];
  38. return true;
  39. }
  40. template <typename Text>
  41. [[nodiscard]] bool link_text(const detail::StringResolver& strings,
  42. const Text& input,
  43. format::StringRef& output) noexcept {
  44. std::string_view value{};
  45. return text_view(input, value) && strings.resolve(value, output);
  46. }
  47. [[nodiscard]] bool link_string(const detail::StringResolver& strings,
  48. std::string_view input,
  49. format::StringRef& output) noexcept {
  50. return strings.resolve(input, output);
  51. }
  52. [[nodiscard]] bool link_policy_text(const detail::StringResolver& strings,
  53. const policy_inventory::Snapshot& source,
  54. policy_inventory::Text input,
  55. format::StringRef& output) noexcept {
  56. std::string_view value{};
  57. return policy_text_view(source, input, value) && strings.resolve(value, output);
  58. }
  59. [[nodiscard]] int hexadecimal_digit(char value) noexcept {
  60. if (value >= '0' && value <= '9') {
  61. return value - '0';
  62. }
  63. if (value >= 'a' && value <= 'f') {
  64. return value - 'a' + 10;
  65. }
  66. return -1;
  67. }
  68. /** Decodes the generated lowercase SHA-256 spelling without accepting a partial digest. */
  69. [[nodiscard]] bool decode_digest(std::string_view input,
  70. std::array<std::byte, 32>& output) noexcept {
  71. output = {};
  72. if (input.size() != output.size() * 2U) {
  73. return false;
  74. }
  75. for (std::size_t index = 0; index < output.size(); ++index) {
  76. const int high = hexadecimal_digit(input[index * 2U]);
  77. const int low = hexadecimal_digit(input[index * 2U + 1U]);
  78. if (high < 0 || low < 0) {
  79. output = {};
  80. return false;
  81. }
  82. output[index] = static_cast<std::byte>((high << 4) | low);
  83. }
  84. return true;
  85. }
  86. template <typename Enum> [[nodiscard]] std::uint32_t semantic_ordinal(Enum value) noexcept {
  87. return static_cast<std::uint32_t>(value) + 1U;
  88. }
  89. /** Appends one canonical tag set and returns its exact range in the shared tag section. */
  90. [[nodiscard]] bool append_binding_tags(std::span<const std::uint32_t> source,
  91. std::vector<format::ActivityBindingTag>& rows,
  92. format::Range& output) {
  93. if (rows.size() >= format::kAbsentIndex || source.size() > format::kAbsentIndex - rows.size()) {
  94. return false;
  95. }
  96. output = {static_cast<std::uint32_t>(rows.size()), static_cast<std::uint32_t>(source.size())};
  97. for (const std::uint32_t tag : source) {
  98. rows.push_back({tag});
  99. }
  100. return true;
  101. }
  102. /** Appends exact package locators and returns their activity-owned range. */
  103. [[nodiscard]] bool
  104. append_binding_locators(std::span<const activity_inventory::PackageLocator> source,
  105. std::vector<format::ActivityBindingLocator>& rows,
  106. format::Range& output) {
  107. if (rows.size() >= format::kAbsentIndex || source.size() > format::kAbsentIndex - rows.size()) {
  108. return false;
  109. }
  110. output = {static_cast<std::uint32_t>(rows.size()), static_cast<std::uint32_t>(source.size())};
  111. for (const activity_inventory::PackageLocator& locator : source) {
  112. rows.push_back({locator.tag, 0, locator.offset});
  113. }
  114. return true;
  115. }
  116. /**
  117. * Translates activity topology and its direct child sections.
  118. * @param inputs Accepted native inventories.
  119. * @param ranges Final parent-to-child ranges.
  120. * @param linker Resolver for the frozen string table.
  121. * @param output Composer-owned final rows.
  122. * @return True when every source row and string reference is valid.
  123. */
  124. [[nodiscard]] bool translate_topology(const Inputs& inputs,
  125. const detail::PreparedRanges& ranges,
  126. const detail::StringResolver& linker,
  127. Storage& output) {
  128. const topology_inventory::Snapshot& topology = *inputs.topology;
  129. const topology_enrichment::Snapshot& enrichment = *inputs.topologyEnrichment;
  130. const policy_inventory::Snapshot& policy = *inputs.policy;
  131. const activity_inventory::Snapshot& activityInventory = *inputs.activityInventory;
  132. output.activities.resize(topology.activities.size());
  133. for (std::size_t index = 0; index < topology.activities.size(); ++index) {
  134. const topology_inventory::Activity& source = topology.activities[index];
  135. const activity_inventory::ActivityVariant& binding = activityInventory.activities[index];
  136. format::Activity& target = output.activities[index];
  137. target.activityIndex = source.activityIndex;
  138. target.definitionHash = source.definitionHash;
  139. target.scenarioIndex = source.scenarioIndex;
  140. target.flags = source.exactFlags;
  141. target.aliases = policy.activityAliases[index];
  142. target.capabilities = ranges.activityCapabilities[index];
  143. target.selectedActivityRootTag =
  144. binding.activityRootTag == 0 ? format::kAbsentIndex : binding.activityRootTag;
  145. target.selectedScenarioTag =
  146. binding.scenarioTag == 0 ? format::kAbsentIndex : binding.scenarioTag;
  147. target.matchmakingConfigTag = binding.bindingEvidence.matchmakingConfigTag;
  148. target.joinStatus = static_cast<std::uint32_t>(binding.joinStatus);
  149. target.bindingDisposition = static_cast<std::uint32_t>(binding.bindingDisposition);
  150. target.bindingReason = static_cast<std::uint32_t>(binding.bindingReason);
  151. target.bindingEvidenceBasis = static_cast<std::uint32_t>(binding.bindingEvidenceBasis);
  152. target.runnableStatus = static_cast<std::uint32_t>(binding.runnableStatus);
  153. target.bindingFlags =
  154. (binding.fullSdkAcceptable ? format::kActivityBindingFullSdkAcceptable : 0U)
  155. | (binding.bindingEvidence.hasInternalName ? format::kActivityBindingHasInternalName
  156. : 0U)
  157. | (binding.bindingEvidence.hasMatchmakingConfig
  158. ? format::kActivityBindingHasMatchmakingConfig
  159. : 0U);
  160. if (!link_text(linker, source.id, target.id)
  161. || !link_text(linker, source.internalName, target.internalName)
  162. || !link_text(linker, source.displayName, target.displayName)
  163. || !append_binding_tags(binding.bindingEvidence.activityRootCandidateTags,
  164. output.activityBindingTags,
  165. target.activityRootCandidateTags)
  166. || !append_binding_tags(binding.bindingEvidence.scenarioNameCandidateTags,
  167. output.activityBindingTags,
  168. target.scenarioNameCandidateTags)
  169. || !append_binding_tags(binding.bindingEvidence.evidenceRootTags,
  170. output.activityBindingTags,
  171. target.evidenceRootTags)
  172. || !append_binding_locators(binding.bindingEvidence.locators,
  173. output.activityBindingLocators,
  174. target.bindingLocators)) {
  175. return false;
  176. }
  177. }
  178. output.scenarios.resize(topology.scenarios.size());
  179. for (std::size_t index = 0; index < topology.scenarios.size(); ++index) {
  180. const topology_inventory::Scenario& source = topology.scenarios[index];
  181. format::Scenario& target = output.scenarios[index];
  182. target.tag = source.tag;
  183. target.bubbles = ranges.scenarioBubbles[index];
  184. target.states = ranges.scenarioStates[index];
  185. target.occurrences = ranges.scenarioOccurrences[index];
  186. if (!link_text(linker, source.id, target.id)
  187. || !link_text(linker, source.name, target.name)) {
  188. return false;
  189. }
  190. }
  191. output.bubbles.resize(topology.bubbles.size());
  192. for (std::size_t index = 0; index < topology.bubbles.size(); ++index) {
  193. const topology_inventory::Bubble& source = topology.bubbles[index];
  194. format::Bubble& target = output.bubbles[index];
  195. target.scenarioIndex = source.scenarioIndex;
  196. target.bubbleOrdinal = source.bubbleOrdinal;
  197. target.nameHash = source.nameHash;
  198. target.states = ranges.bubbleStates[index];
  199. if (!link_text(linker, source.id, target.id)
  200. || !link_text(linker, enrichment.bubbleNames[index], target.name)) {
  201. return false;
  202. }
  203. }
  204. output.states.resize(topology.states.size());
  205. for (std::size_t index = 0; index < topology.states.size(); ++index) {
  206. const topology_inventory::State& source = topology.states[index];
  207. format::State& target = output.states[index];
  208. target.scenarioIndex = source.scenarioIndex;
  209. target.bubbleIndex = source.bubbleIndex;
  210. target.stateOrdinal = source.stateOrdinal;
  211. target.entryIndex = source.entryIndex;
  212. target.sliceSetIndex = source.sliceSetIndex;
  213. target.mapBubbleIndex = source.mapBubbleIndex;
  214. target.stateHash = source.stateHash;
  215. target.publicValue = source.rawU32At12;
  216. target.flags = kStateExtractionComplete | (source.enabled ? kStateEnabled : 0U);
  217. target.registryTag = source.registryTag;
  218. if (!link_text(linker, source.id, target.id)
  219. || !link_text(linker, source.entryId, target.entryId)
  220. || !link_text(linker, source.registryId, target.registryId)) {
  221. return false;
  222. }
  223. }
  224. output.objects.resize(topology.objects.size());
  225. for (std::size_t index = 0; index < topology.objects.size(); ++index) {
  226. const topology_inventory::Object& source = topology.objects[index];
  227. format::Object& target = output.objects[index];
  228. target.objectTag = source.objectTag;
  229. target.objectKey = source.objectKey;
  230. target.slots = ranges.objectSlots[index];
  231. target.configCount = source.configCount;
  232. target.descriptorCount = source.descriptorCount;
  233. target.placedSubblockCount = source.placedSubblockCount;
  234. target.placedLeafCount = source.placedLeafCount;
  235. target.placedHopCount = source.placedHopCount;
  236. target.bareTargetCount = source.bareTargetCount;
  237. target.replicatedPlacementCount = source.replicatedPlacementCount;
  238. if (!link_text(linker, source.id, target.id)) {
  239. return false;
  240. }
  241. }
  242. output.occurrences.resize(topology.occurrences.size());
  243. for (std::size_t index = 0; index < topology.occurrences.size(); ++index) {
  244. const topology_inventory::Occurrence& source = topology.occurrences[index];
  245. format::Occurrence& target = output.occurrences[index];
  246. target.scenarioIndex = source.scenarioIndex;
  247. target.bubbleIndex = source.bubbleIndex;
  248. target.stateIndex = source.stateIndex;
  249. target.objectIndex = source.objectIndex;
  250. target.registryField = source.registryField;
  251. target.objectOrdinal = source.objectOrdinal;
  252. if (!link_text(linker, source.id, target.id)
  253. || !link_text(linker, source.contextRegistryKey, target.contextRegistryKey)
  254. || !link_text(linker, source.registryId, target.registryId)
  255. || !link_text(linker, source.entryId, target.entryId)) {
  256. return false;
  257. }
  258. }
  259. output.slots.resize(topology.slots.size());
  260. for (std::size_t index = 0; index < topology.slots.size(); ++index) {
  261. const topology_inventory::Slot& source = topology.slots[index];
  262. const topology_enrichment::Slot& linked = enrichment.slots[index];
  263. format::Slot& target = output.slots[index];
  264. target.objectIndex = source.objectIndex;
  265. target.slotIndex = source.slotIndex;
  266. target.slotType = source.slotType;
  267. target.componentClass = linked.componentClass;
  268. target.senseSchema = linked.senseSchema;
  269. target.authSchema = linked.authSchema;
  270. target.flags = linked.flags;
  271. target.reserved = linked.dialogueCueCount;
  272. target.aliases = policy.slotAliases[index];
  273. target.capabilities = ranges.slotCapabilities[index];
  274. if (!link_text(linker, source.id, target.id) || !link_text(linker, linked.name, target.name)
  275. || !link_text(linker, linked.senseSchemaId, target.senseSchemaId)
  276. || !link_text(linker, linked.authSchemaId, target.authSchemaId)) {
  277. return false;
  278. }
  279. }
  280. return true;
  281. }
  282. /** Copies policy rows after resolving every handle in the policy-owned pool. */
  283. [[nodiscard]] bool translate_policy(const policy_inventory::Snapshot& source,
  284. const detail::StringResolver& linker,
  285. Storage& output) {
  286. output.texts.resize(source.texts.size());
  287. for (std::size_t index = 0; index < source.texts.size(); ++index) {
  288. const policy_inventory::TextRow& input = source.texts[index];
  289. format::Text& target = output.texts[index];
  290. target.kind = input.kind;
  291. target.reserved = input.reserved;
  292. if (!link_policy_text(linker, source, input.value, target.value)) {
  293. return false;
  294. }
  295. }
  296. output.capabilities.resize(source.capabilities.size());
  297. for (std::size_t index = 0; index < source.capabilities.size(); ++index) {
  298. const policy_inventory::Capability& input = source.capabilities[index];
  299. format::Capability& target = output.capabilities[index];
  300. target.subjectKind = input.subjectKind;
  301. target.subjectIndex = input.subjectIndex;
  302. target.exposureFlags = input.exposureFlags;
  303. target.candidateExposureFlags = input.candidateExposureFlags;
  304. target.gates = input.gates;
  305. target.refusals = input.refusals;
  306. if (!link_policy_text(linker, source, input.id, target.id)
  307. || !link_policy_text(linker, source, input.operation, target.operation)
  308. || !link_policy_text(linker, source, input.valueSchemaId, target.valueSchemaId)) {
  309. return false;
  310. }
  311. }
  312. output.gates.resize(source.gates.size());
  313. for (std::size_t index = 0; index < source.gates.size(); ++index) {
  314. const policy_inventory::Gate& input = source.gates[index];
  315. format::Gate& target = output.gates[index];
  316. if (!link_policy_text(linker, source, input.gate, target.gate)
  317. || !link_policy_text(linker, source, input.status, target.status)
  318. || !link_policy_text(linker, source, input.reasonCode, target.reasonCode)
  319. || !link_policy_text(linker, source, input.required, target.required)
  320. || !link_policy_text(linker, source, input.observed, target.observed)
  321. || !link_policy_text(linker, source, input.wouldConfirm, target.wouldConfirm)) {
  322. return false;
  323. }
  324. }
  325. output.refusals.resize(source.refusals.size());
  326. for (std::size_t index = 0; index < source.refusals.size(); ++index) {
  327. const policy_inventory::Refusal& input = source.refusals[index];
  328. format::Refusal& target = output.refusals[index];
  329. target.reasonCodes = input.reasonCodes;
  330. target.capabilityIndex = input.capabilityIndex;
  331. target.reserved = input.reserved;
  332. if (!link_policy_text(linker, source, input.id, target.id)
  333. || !link_policy_text(linker, source, input.exposure, target.exposure)
  334. || !link_policy_text(linker, source, input.status, target.status)) {
  335. return false;
  336. }
  337. }
  338. return true;
  339. }
  340. /** Copies actor, RSAT, squad, and panel placement sections. */
  341. [[nodiscard]] bool
  342. translate_native_rows(const Inputs& inputs, const detail::StringResolver& linker, Storage& output) {
  343. const actor_rsat_inventory::Snapshot& actorRsat = *inputs.actorRsat;
  344. const squad_inventory::Snapshot& squads = *inputs.squads;
  345. const authored_scene_inventory::Snapshot& authoredScenes = *inputs.authoredScenes;
  346. const behavior_inventory::Snapshot& behaviors = *inputs.behaviors;
  347. output.actorClasses.resize(actorRsat.actorClasses.size());
  348. for (std::size_t index = 0; index < actorRsat.actorClasses.size(); ++index) {
  349. const actor_rsat_inventory::ActorClass& input = actorRsat.actorClasses[index];
  350. format::ActorClass& target = output.actorClasses[index];
  351. target.definitionTag = input.definitionTag;
  352. target.nameHash = input.nameHash;
  353. target.rsatTag = input.rsatTag;
  354. target.rsatReverseDefinitionTag = input.rsatReverseDefinitionTag;
  355. target.objectType = input.objectType;
  356. target.descriptorArrayOffset = input.descriptorArrayOffset;
  357. target.descriptorArrayRelative = input.descriptorArrayRelative;
  358. target.descriptorArrayHeaderOffset = input.descriptorArrayHeaderOffset;
  359. target.descriptorArrayDataOffset = input.descriptorArrayDataOffset;
  360. target.descriptorElementClass = input.descriptorElementClass;
  361. target.descriptors = input.descriptors;
  362. target.dynamicPresenceTailCount = input.dynamicPresenceTailCount;
  363. target.authoredSpawnProfile = input.authoredSpawnProfile;
  364. if (!link_text(linker, input.id, target.id)) {
  365. return false;
  366. }
  367. }
  368. output.actorMessageSchemas.resize(actorRsat.messageSchemas.size());
  369. for (std::size_t index = 0; index < actorRsat.messageSchemas.size(); ++index) {
  370. const actor_rsat_inventory::ActorMessageSchema& input = actorRsat.messageSchemas[index];
  371. format::ActorMessageSchema& target = output.actorMessageSchemas[index];
  372. target.definitionHandle = input.definitionHandle;
  373. target.durableKey = input.durableKey;
  374. target.ownerClass = input.ownerClass;
  375. target.handlerSlot = input.handlerSlot;
  376. target.bodyType = input.bodyType;
  377. target.provenance = input.provenance;
  378. target.commands = input.commands;
  379. target.flags = input.flags;
  380. if (!link_text(linker, input.name, target.name)) {
  381. return false;
  382. }
  383. }
  384. output.actorCommandDefinitions.resize(actorRsat.commandDefinitions.size());
  385. for (std::size_t index = 0; index < actorRsat.commandDefinitions.size(); ++index) {
  386. const actor_rsat_inventory::ActorCommandDefinition& input =
  387. actorRsat.commandDefinitions[index];
  388. format::ActorCommandDefinition& target = output.actorCommandDefinitions[index];
  389. target.selector = input.selector;
  390. target.payloadHandle = input.payloadHandle;
  391. target.effect = input.effect;
  392. target.provenance = input.provenance;
  393. target.factionNone = input.factionNone;
  394. target.factionRemoved = input.factionRemoved;
  395. target.factionHostileToAll = input.factionHostileToAll;
  396. target.flags = input.flags;
  397. if (!link_text(linker, input.name, target.name)
  398. || !link_text(linker, input.factionNoneName, target.factionNoneName)
  399. || !link_text(linker, input.factionRemovedName, target.factionRemovedName)
  400. || !link_text(linker, input.factionHostileToAllName, target.factionHostileToAllName)) {
  401. return false;
  402. }
  403. }
  404. output.actorBehaviorProfiles.resize(actorRsat.behaviorProfiles.size());
  405. for (std::size_t index = 0; index < actorRsat.behaviorProfiles.size(); ++index) {
  406. const actor_rsat_inventory::ActorBehaviorProfile& input = actorRsat.behaviorProfiles[index];
  407. format::ActorBehaviorProfile& target = output.actorBehaviorProfiles[index];
  408. target.actorClassIndex = input.actorClassIndex;
  409. target.behaviorConfigTag = input.behaviorConfigTag;
  410. target.behaviorConfigClass = input.behaviorConfigClass;
  411. target.behaviorConfigOffset = input.behaviorConfigOffset;
  412. target.defaultFaction = input.defaultFaction;
  413. target.behaviorProvenance = input.behaviorProvenance;
  414. target.factionProvenance = input.factionProvenance;
  415. target.flags = input.flags;
  416. }
  417. output.simulationEventDefinitions.resize(actorRsat.simulationEvents.size());
  418. for (std::size_t index = 0; index < actorRsat.simulationEvents.size(); ++index) {
  419. const actor_rsat_inventory::SimulationEventDefinition& input =
  420. actorRsat.simulationEvents[index];
  421. format::SimulationEventDefinition& target = output.simulationEventDefinitions[index];
  422. target.eventType = input.eventType;
  423. target.primarySchema = input.primarySchema;
  424. target.secondarySchema = input.secondarySchema;
  425. target.provenance = input.provenance;
  426. target.descriptorEvidenceAddress = input.descriptorEvidenceAddress;
  427. target.primaryEvidenceAddress = input.primaryEvidenceAddress;
  428. target.secondaryEvidenceAddress = input.secondaryEvidenceAddress;
  429. target.flags = input.flags;
  430. if (!link_text(linker, input.name, target.name)) {
  431. return false;
  432. }
  433. }
  434. output.runtimeSchemas = actorRsat.runtimeSchemas;
  435. output.runtimeFields = actorRsat.runtimeFields;
  436. output.runtimeTypeDefinitions.resize(actorRsat.runtimeTypes.size());
  437. for (std::size_t index = 0; index < actorRsat.runtimeTypes.size(); ++index) {
  438. const actor_rsat_inventory::RuntimeTypeDefinition& input = actorRsat.runtimeTypes[index];
  439. format::RuntimeTypeDefinition& target = output.runtimeTypeDefinitions[index];
  440. target.codecFamilies = input.codecFamilies;
  441. target.typeCode = input.typeCode;
  442. target.decodedSize = input.decodedSize;
  443. target.fixedBits = input.fixedBits;
  444. target.minimumBits = input.minimumBits;
  445. target.maximumBits = input.maximumBits;
  446. target.writerEvidenceAddress = input.writerEvidenceAddress;
  447. target.readerEvidenceAddress = input.readerEvidenceAddress;
  448. target.flags = input.flags;
  449. if (!link_text(linker, input.name, target.name)) {
  450. return false;
  451. }
  452. }
  453. output.sobjectRsats = actorRsat.sobjectRsats;
  454. output.sobjectRsatDescriptors = actorRsat.sobjectRsatDescriptors;
  455. output.sobjectRsatFieldBindings = actorRsat.sobjectRsatFieldBindings;
  456. output.actorStateNames = actorRsat.actorStateNames;
  457. output.actorSequenceTables = actorRsat.sequenceTables;
  458. output.actorSequenceBindings = actorRsat.sequenceBindings;
  459. output.actorAbilities = actorRsat.actorAbilities;
  460. output.actorAbilityTargets = actorRsat.actorAbilityTargets;
  461. output.actorSequenceEntries.reserve(actorRsat.sequenceEntries.size());
  462. for (const auto& input : actorRsat.sequenceEntries) {
  463. auto row = input.row;
  464. if (!link_string(linker, input.id, row.id) || !link_string(linker, input.name, row.name)
  465. || !link_string(linker, input.symbol, row.symbol)
  466. || !link_string(linker, input.sourcePath, row.sourcePath)) {
  467. return false;
  468. }
  469. output.actorSequenceEntries.push_back(row);
  470. }
  471. output.entityTypeDefinitions.resize(actorRsat.entityTypes.size());
  472. for (std::size_t index = 0; index < actorRsat.entityTypes.size(); ++index) {
  473. const actor_rsat_inventory::EntityTypeDefinition& input = actorRsat.entityTypes[index];
  474. format::EntityTypeDefinition& target = output.entityTypeDefinitions[index];
  475. target.entityType = input.entityType;
  476. target.baselineSchema = input.baselineSchema;
  477. target.updateSchema = input.updateSchema;
  478. target.provenance = input.provenance;
  479. target.vtableEvidenceAddress = input.vtableEvidenceAddress;
  480. target.baselineEvidenceAddress = input.baselineEvidenceAddress;
  481. target.updateEvidenceAddress = input.updateEvidenceAddress;
  482. target.flags = input.flags;
  483. if (!link_text(linker, input.name, target.name)) {
  484. return false;
  485. }
  486. }
  487. output.rsatDescriptors.resize(actorRsat.descriptors.size());
  488. for (std::size_t index = 0; index < actorRsat.descriptors.size(); ++index) {
  489. const actor_rsat_inventory::RsatDescriptor& input = actorRsat.descriptors[index];
  490. format::RsatDescriptor& target = output.rsatDescriptors[index];
  491. target.actorClassIndex = input.actorClassIndex;
  492. target.rsatTag = input.rsatTag;
  493. target.descriptorOrdinal = input.descriptorOrdinal;
  494. target.descriptorOffset = input.descriptorOffset;
  495. target.descriptorElementClass = input.descriptorElementClass;
  496. target.componentTag = input.componentTag;
  497. target.schemaIndex = input.schemaIndex;
  498. target.schemaTag = input.schemaTag;
  499. target.schemaFieldCount = input.schemaFieldCount;
  500. target.schemaFirstFieldRuntimeGate = input.schemaFirstFieldRuntimeGate;
  501. target.schemaFirstFieldRawU32At10 = input.schemaFirstFieldRawU32At10;
  502. target.flags = input.flags;
  503. target.dynamicPresenceTailOrdinal = input.dynamicPresenceTailOrdinal;
  504. target.rawRow = input.rawRow;
  505. if (!link_text(linker, input.id, target.id)) {
  506. return false;
  507. }
  508. }
  509. output.rsatSchemas.resize(actorRsat.schemas.size());
  510. for (std::size_t index = 0; index < actorRsat.schemas.size(); ++index) {
  511. const actor_rsat_inventory::RsatSchema& input = actorRsat.schemas[index];
  512. format::RsatSchema& target = output.rsatSchemas[index];
  513. target.schemaTag = input.schemaTag;
  514. target.schemaClass = input.schemaClass;
  515. target.fieldCount = input.fieldCount;
  516. target.fieldArrayOffset = input.fieldArrayOffset;
  517. target.fieldArrayRelative = input.fieldArrayRelative;
  518. target.fieldArrayHeaderOffset = input.fieldArrayHeaderOffset;
  519. target.fieldArrayDataOffset = input.fieldArrayDataOffset;
  520. target.fieldElementClass = input.fieldElementClass;
  521. target.firstFieldRuntimeGate = input.firstFieldRuntimeGate;
  522. target.firstFieldRawU32At10 = input.firstFieldRawU32At10;
  523. target.flags = input.flags;
  524. target.fields = input.fields;
  525. if (!link_text(linker, input.id, target.id)) {
  526. return false;
  527. }
  528. }
  529. output.rsatFields.resize(actorRsat.fields.size());
  530. for (std::size_t index = 0; index < actorRsat.fields.size(); ++index) {
  531. output.rsatFields[index].rawRow = actorRsat.fields[index].rawRow;
  532. }
  533. output.squads.resize(squads.squads.size());
  534. for (std::size_t index = 0; index < squads.squads.size(); ++index) {
  535. const squad_inventory::Squad& input = squads.squads[index];
  536. format::Squad& target = output.squads[index];
  537. target.scenarioIndex = input.scenarioIndex;
  538. target.objectIndex = input.objectIndex;
  539. target.slotIndex = input.slotIndex;
  540. target.spawnerConfigTag = input.spawnerConfigTag;
  541. target.spawnRuleConfigTag = input.spawnRuleConfigTag;
  542. target.flags = input.flags;
  543. target.occurrenceIndex = input.occurrenceIndex;
  544. target.members = input.members;
  545. target.anchors = input.anchors;
  546. if (!link_string(linker, input.id, target.id)) {
  547. return false;
  548. }
  549. }
  550. output.squadMembers.resize(squads.members.size());
  551. for (std::size_t index = 0; index < squads.members.size(); ++index) {
  552. const squad_inventory::SquadMember& input = squads.members[index];
  553. format::SquadMember& target = output.squadMembers[index];
  554. target.squadIndex = input.squadIndex;
  555. target.memberOrdinal = input.memberOrdinal;
  556. target.memberKey = input.memberKey;
  557. target.actorClassIndex = input.actorClassIndex;
  558. target.flags = input.flags;
  559. target.candidateCounts = input.candidateCounts;
  560. target.defaultCount = input.defaultCount;
  561. if (!link_string(linker, input.id, target.id)) {
  562. return false;
  563. }
  564. }
  565. output.squadAnchors.resize(squads.anchors.size());
  566. for (std::size_t index = 0; index < squads.anchors.size(); ++index) {
  567. const squad_inventory::SquadAnchor& input = squads.anchors[index];
  568. format::SquadAnchor& target = output.squadAnchors[index];
  569. target.squadIndex = input.squadIndex;
  570. target.pointOrdinal = input.pointOrdinal;
  571. target.objectListTag = input.objectListTag;
  572. target.placementOrdinal = input.placementOrdinal;
  573. target.flags = input.flags;
  574. target.placedEntryIdentity = input.placedEntryIdentity;
  575. target.positionBits = input.positionBits;
  576. if (!link_string(linker, input.id, target.id)) {
  577. return false;
  578. }
  579. }
  580. output.authoredSceneResources.resize(authoredScenes.resources.size());
  581. for (std::size_t index = 0; index < authoredScenes.resources.size(); ++index) {
  582. const authored_scene_inventory::Resource& input = authoredScenes.resources[index];
  583. format::AuthoredSceneResource& target = output.authoredSceneResources[index];
  584. target.slotIndex = input.slotIndex;
  585. target.configTag = input.configTag;
  586. target.descriptorOffset = input.descriptorOffset;
  587. target.resourceFieldOffset = input.resourceFieldOffset;
  588. target.resourceTag = input.resourceTag;
  589. target.resourceClass = input.resourceClass;
  590. target.flags = input.flags;
  591. target.reserved = input.reserved;
  592. if (!link_text(linker, input.id, target.id)) {
  593. return false;
  594. }
  595. }
  596. output.authoredSceneEventKeys.resize(authoredScenes.eventKeys.size());
  597. for (std::size_t index = 0; index < authoredScenes.eventKeys.size(); ++index) {
  598. const authored_scene_inventory::EventKey& input = authoredScenes.eventKeys[index];
  599. format::AuthoredSceneEventKey& target = output.authoredSceneEventKeys[index];
  600. target.sceneSlotIndex = input.slotIndex;
  601. target.resourceTag = input.resourceTag;
  602. target.graphTag = input.graphTag;
  603. target.gateOffset = input.gateOffset;
  604. target.ordinal = input.ordinal;
  605. target.key = input.key;
  606. target.flags = input.flags;
  607. target.reserved = input.reserved;
  608. if (!link_text(linker, input.id, target.id)) {
  609. return false;
  610. }
  611. }
  612. output.authoredSceneSquadEdges.resize(authoredScenes.squadEdges.size());
  613. for (std::size_t index = 0; index < authoredScenes.squadEdges.size(); ++index) {
  614. const authored_scene_inventory::SquadEdge& input = authoredScenes.squadEdges[index];
  615. format::AuthoredSceneSquadEdge& target = output.authoredSceneSquadEdges[index];
  616. target.sceneSlotIndex = input.sceneSlotIndex;
  617. target.squadSlotIndex = input.squadSlotIndex;
  618. target.configTag = input.configTag;
  619. target.descriptorOffset = input.descriptorOffset;
  620. target.referenceFieldOffset = input.referenceFieldOffset;
  621. target.targetObjectKey = input.targetObjectKey;
  622. target.flags = input.flags;
  623. target.reserved = input.reserved;
  624. if (!link_text(linker, input.id, target.id)) {
  625. return false;
  626. }
  627. }
  628. output.taskTargets.resize(authoredScenes.taskTargets.size());
  629. for (std::size_t index = 0; index < authoredScenes.taskTargets.size(); ++index) {
  630. const authored_scene_inventory::TaskTarget& input = authoredScenes.taskTargets[index];
  631. format::TaskTarget& target = output.taskTargets[index];
  632. target.taskSlotIndex = input.taskSlotIndex;
  633. target.objectiveSlotIndex = input.objectiveSlotIndex;
  634. target.configTag = input.configTag;
  635. target.descriptorOffset = input.descriptorOffset;
  636. target.referenceFieldOffset = input.referenceFieldOffset;
  637. target.targetObjectKey = input.targetObjectKey;
  638. target.bitIndex = input.bitIndex;
  639. target.flags = input.flags;
  640. target.reserved = input.reserved;
  641. if (!link_text(linker, input.id, target.id)) {
  642. return false;
  643. }
  644. }
  645. output.dialogueCues = authoredScenes.dialogueCues;
  646. output.combatObjectiveGroups = authoredScenes.combatObjectiveGroups;
  647. output.dialogueCueTexts.resize(authoredScenes.dialogueCueTexts.size());
  648. for (std::size_t index = 0; index < authoredScenes.dialogueCueTexts.size(); ++index) {
  649. const authored_scene_inventory::DialogueCueText& input =
  650. authoredScenes.dialogueCueTexts[index];
  651. format::DialogueCueText& target = output.dialogueCueTexts[index];
  652. target.slotIndex = input.slotIndex;
  653. target.cueIndex = input.cueIndex;
  654. target.definitionHash = input.definitionHash;
  655. target.containerTag = input.containerTag;
  656. target.stringHash = input.stringHash;
  657. if (!link_text(linker, input.id, target.id)
  658. || !link_text(linker, input.text, target.text)) {
  659. return false;
  660. }
  661. }
  662. output.directiveElements.resize(authoredScenes.directiveElements.size());
  663. for (std::size_t index = 0; index < authoredScenes.directiveElements.size(); ++index) {
  664. const authored_scene_inventory::DirectiveElement& input =
  665. authoredScenes.directiveElements[index];
  666. format::DirectiveElement& target = output.directiveElements[index];
  667. target.slotIndex = input.slotIndex;
  668. target.nameHash = input.nameHash;
  669. target.elementIndex = input.elementIndex;
  670. target.elementCount = input.elementCount;
  671. target.titleContainerTag = input.titleContainerTag;
  672. target.titleStringHash = input.titleStringHash;
  673. target.descriptionContainerTag = input.descriptionContainerTag;
  674. target.descriptionStringHash = input.descriptionStringHash;
  675. target.progressContainerTag = input.progressContainerTag;
  676. target.progressStringHash = input.progressStringHash;
  677. target.flags = input.flags;
  678. if (!link_text(linker, input.id, target.id) || !link_text(linker, input.title, target.title)
  679. || !link_text(linker, input.description, target.description)
  680. || !link_text(linker, input.progress, target.progress)) {
  681. return false;
  682. }
  683. }
  684. output.behaviorPrograms.reserve(behaviors.programs.size());
  685. for (const behavior_inventory::Program& input : behaviors.programs) {
  686. output.behaviorPrograms.push_back({input.rootTag,
  687. {input.firstInput, input.inputCount},
  688. {input.firstWrite, input.writeCount},
  689. input.nodeCount,
  690. input.expressionCount});
  691. }
  692. output.behaviorInputs.reserve(behaviors.inputs.size());
  693. for (const behavior_inventory::Input& input : behaviors.inputs) {
  694. output.behaviorInputs.push_back({input.programRow,
  695. input.nodeOffset,
  696. input.expressionOffset,
  697. input.channelHash,
  698. input.inputOrMode,
  699. input.nativeOverride,
  700. input.activeField,
  701. input.selector,
  702. input.role,
  703. 0});
  704. }
  705. output.behaviorChannelWrites.reserve(behaviors.writes.size());
  706. for (const behavior_inventory::ChannelWrite& input : behaviors.writes) {
  707. output.behaviorChannelWrites.push_back(
  708. {input.programRow, input.nodeOffset, input.channelHash, 0});
  709. }
  710. output.behaviorOwners.reserve(behaviors.owners.size());
  711. for (const behavior_inventory::Owner& input : behaviors.owners) {
  712. output.behaviorOwners.push_back(
  713. {input.programRow,
  714. input.actorClassIndex,
  715. input.configTag,
  716. input.configFieldOffset,
  717. input.buildOrdinal,
  718. input.descriptorOrdinal,
  719. input.submitterSubtype,
  720. static_cast<format::BehaviorSubmissionKind>(input.submissionKind)});
  721. }
  722. for (std::size_t ownerIndex = 0; ownerIndex < output.behaviorOwners.size(); ++ownerIndex) {
  723. if (ownerIndex > (std::numeric_limits<std::uint32_t>::max)()) {
  724. return false;
  725. }
  726. const format::BehaviorOwner& owner = output.behaviorOwners[ownerIndex];
  727. for (std::size_t memberIndex = 0; memberIndex < output.squadMembers.size(); ++memberIndex) {
  728. if (memberIndex > (std::numeric_limits<std::uint32_t>::max)()) {
  729. return false;
  730. }
  731. const format::SquadMember& member = output.squadMembers[memberIndex];
  732. if (member.actorClassIndex != owner.actorClassIndex
  733. || member.squadIndex >= output.squads.size()) {
  734. continue;
  735. }
  736. const format::Squad& squad = output.squads[member.squadIndex];
  737. if (squad.occurrenceIndex >= output.occurrences.size()) {
  738. return false;
  739. }
  740. const format::Occurrence& occurrence = output.occurrences[squad.occurrenceIndex];
  741. output.behaviorActivityBindings.push_back({static_cast<std::uint32_t>(ownerIndex),
  742. member.squadIndex,
  743. static_cast<std::uint32_t>(memberIndex),
  744. occurrence.scenarioIndex,
  745. squad.occurrenceIndex,
  746. occurrence.stateIndex,
  747. occurrence.objectIndex,
  748. 0});
  749. }
  750. }
  751. return true;
  752. }
  753. } // namespace
  754. /** Translates topology, policy and native rows into pack storage. @return False on failure. */
  755. bool detail::translate_rows(const Inputs& inputs,
  756. const PreparedRanges& ranges,
  757. const StringResolver& strings,
  758. Storage& output) {
  759. if (!translate_topology(inputs, ranges, strings, output)) {
  760. return false;
  761. }
  762. if (!translate_policy(*inputs.policy, strings, output)) {
  763. return false;
  764. }
  765. if (!translate_native_rows(inputs, strings, output)) {
  766. return false;
  767. }
  768. return true;
  769. }
  770. } // namespace sunrise::client::content::activity::sdk_generation::pack_composer