Browse Source

Size the ability row table to every subclass's remembered picks

Since ability picks are stored per subclass item instead of per
character, one character can need two ability rows per subclass: one at
the default selection and one for its changed picks. The row table stayed
at the earlier model of a single changed subclass per character, 3
characters by up to 4 rows, so once a character changed the picks of a
second subclass the row that no longer fit was dropped. That subclass
then published no abilities at all: no ability icons and no movement
ability, while the default selection kept working because its row is
published first.

The overflow returned without a report, so the extraction pass still
logged result=ok and the drop was invisible.

Sizes the table to 3 characters by 3 owned subclasses by 2 rows, and
reports the overflow so a future one is not silent.

Bumps the cache format version, because a cache written at the wider
capacity fails `counts_fit` on a build that still has the narrow one.
That is an invalid cache, not a stale one, so it fails the boot instead
of rebuilding; a version difference is what makes such a cache rebuild.
Yakariii123 1 week ago
parent
commit
f2894c2bd5

+ 2 - 0
Sunrise/src/client/content/items/packages/package_subclass_build.cpp

@@ -124,6 +124,8 @@ bool build_character_abilities(
                              std::uint16_t socketEntryListIndex,
                              std::uint16_t socketEntryListIndex,
                              const domain::Selection& selection) noexcept {
                              const domain::Selection& selection) noexcept {
         if (count >= output.size()) {
         if (count >= output.size()) {
+            // A dropped row leaves that subclass and selection with no published abilities.
+            report_ability_failure("capacity", character, socketEntryListIndex, output.size());
             return;
             return;
         }
         }
         domain::Definition row{};
         domain::Definition row{};

+ 5 - 3
Sunrise/src/state/build_data/abilities/definition.h

@@ -14,10 +14,12 @@ inline constexpr std::size_t kBucketHashCapacity = 16;
 inline constexpr std::size_t kOverflowCapacity = 32;
 inline constexpr std::size_t kOverflowCapacity = 32;
 /**
 /**
  * One row per distinct subclass and ability selection the configured characters use. Each
  * One row per distinct subclass and ability selection the configured characters use. Each
- * character publishes a row for every subclass it owns at the default selection, plus one for the
- * equipped subclass's real picks when those differ: 3 characters by up to 4 rows.
+ * character publishes a row for every subclass it owns at the default selection, plus one for
+ * every one of those subclasses whose remembered picks differ, since the picks are kept per
+ * subclass item rather than only for the equipped one: 3 characters by 3 owned subclasses by 2
+ * rows.
  */
  */
-inline constexpr std::size_t kDefinitionCapacity = 12;
+inline constexpr std::size_t kDefinitionCapacity = 18;
 /** All bits set marks a bucket no entry claimed. */
 /** All bits set marks a bucket no entry claimed. */
 inline constexpr std::uint8_t kEmptyBucketKind = 0xFF;
 inline constexpr std::uint8_t kEmptyBucketKind = 0xFF;
 
 

+ 1 - 1
Sunrise/src/state/build_data/cache/records/format.h

@@ -31,7 +31,7 @@ namespace sunrise::state::build_data::cache::records {
 /** These 8 ASCII bytes mark a Sunrise build-data file. */
 /** These 8 ASCII bytes mark a Sunrise build-data file. */
 inline constexpr std::array<char, 8> kCacheMagic{'S', 'U', 'N', 'R', 'I', 'S', 'E', 'B'};
 inline constexpr std::array<char, 8> kCacheMagic{'S', 'U', 'N', 'R', 'I', 'S', 'E', 'B'};
 /** Bump when stored layouts or extracted values change; other versions are rebuilt. */
 /** Bump when stored layouts or extracted values change; other versions are rebuilt. */
-inline constexpr std::uint32_t kCacheFormatVersion = 65;
+inline constexpr std::uint32_t kCacheFormatVersion = 66;
 /** Signed -1 on disk means there is no equipment slot. */
 /** Signed -1 on disk means there is no equipment slot. */
 inline constexpr std::int8_t kAbsentEquipmentSlot = -1;
 inline constexpr std::int8_t kAbsentEquipmentSlot = -1;
 /** The standard 64-bit FNV-1a offset basis starts the payload checksum. */
 /** The standard 64-bit FNV-1a offset basis starts the payload checksum. */