Просмотр исходного кода

Preserve required reward mappings and finish review cleanup

Zach 1 месяц назад
Родитель
Сommit
479c12c968

+ 0 - 12
Sunrise/Sunrise.vcxproj.filters

@@ -67,16 +67,4 @@
     <None Include="vendor\lua\README.md"><Filter>Vendor\Lua</Filter></None>
     <None Include="vendor\lua\UPSTREAM_README"><Filter>Vendor\Lua</Filter></None>
   </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="src\client\content\items\packages\package_reward_build.cpp" />
-    <ClInclude Include="src\client\content\items\packages\package_reward_build.h" />
-    <ClInclude Include="src\middleware\content\packages\tables\field_reader.h" />
-    <ClCompile Include="src\state\build_data\cache\records\cache_reward_records.cpp" />
-    <ClInclude Include="src\state\build_data\rewards\definition.h" />
-    <ClCompile Include="src\state\build_data\rewards\reward_catalog.cpp" />
-    <ClInclude Include="src\state\build_data\rewards\reward_catalog.h" />
-    <ClCompile Include="src\state\rewards\reward_resolver.cpp" />
-    <ClInclude Include="src\state\rewards\reward_resolver.h" />
-    <ClInclude Include="src\middleware\content\packages\tables\unlock_opcode.h" />
-  </ItemGroup>
 </Project>

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

@@ -53,9 +53,9 @@ constexpr std::size_t kAcquiredFlagField = 0xDA;
 /** Byte offsets inside the serialized reward rows. */
 constexpr std::size_t kEntryQuantityOffset = 4;
 constexpr std::size_t kEntryPoolOffset = 8;
+constexpr std::size_t kEntryMappingOffset = 10;
 constexpr std::size_t kEntryCategoryOffset = 20;
 constexpr std::size_t kEntryWeightOffset = 24;
-constexpr std::size_t kEntryBucketOffset = 28;
 constexpr std::size_t kEntryConditionOffset = 32;
 constexpr std::size_t kEntryModifiersOffset = 48;
 constexpr std::size_t kEntrySocketsOffset = 64;
@@ -113,9 +113,9 @@ bool read_reward_entry(std::span<const std::byte> blob,
     return tables::read(blob, at, entry.itemIndex)
            && tables::read(blob, at + kEntryQuantityOffset, entry.quantity)
            && tables::read(blob, at + kEntryPoolOffset, entry.poolIndex)
+           && tables::read(blob, at + kEntryMappingOffset, entry.mappingIndex)
            && tables::read(blob, at + kEntryCategoryOffset, entry.categoryHash)
            && tables::read(blob, at + kEntryWeightOffset, entry.weight)
-           && tables::read(blob, at + kEntryBucketOffset, entry.bucketHash)
            && std::isfinite(entry.weight) && entry.weight >= 0;
 }
 

+ 1 - 1
Sunrise/src/middleware/content/packages/tables/unlock_expression.h

@@ -9,7 +9,7 @@
 
 namespace sunrise::middleware::content::packages::tables {
 
-/** Record and node field detection rejects values above 20 as non-expression data. */
+/** Upstream's record/node field heuristic; this is not the reward evaluator's opcode limit. */
 inline constexpr std::uint32_t kExpressionDetectionOpcodeCeiling = 20;
 
 /**

+ 2 - 2
Sunrise/src/state/build_data/cache/records/cache_reward_records.cpp

@@ -20,9 +20,9 @@ bool encode(const rewards::Entry& value, RewardEntryRecord& record) noexcept {
     record = {};
     record.itemIndex = value.itemIndex;
     record.poolIndex = value.poolIndex;
+    record.mappingIndex = value.mappingIndex;
     record.quantity = value.quantity;
     record.categoryHash = value.categoryHash;
-    record.bucketHash = value.bucketHash;
     record.weight = value.weight;
     record.condition = {value.condition.first, value.condition.count};
     record.modifiers = {value.modifiers.first, value.modifiers.count};
@@ -34,9 +34,9 @@ bool decode(const RewardEntryRecord& record, rewards::Entry& value) noexcept {
     value = {};
     value.itemIndex = record.itemIndex;
     value.poolIndex = record.poolIndex;
+    value.mappingIndex = record.mappingIndex;
     value.quantity = record.quantity;
     value.categoryHash = record.categoryHash;
-    value.bucketHash = record.bucketHash;
     value.weight = record.weight;
     value.condition = {record.condition.first, record.condition.count};
     value.modifiers = {record.modifiers.first, record.modifiers.count};

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

@@ -32,7 +32,7 @@ namespace sunrise::state::build_data::cache::records {
 /** 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'};
 /** Bump when stored layouts or extracted values change; other versions are rebuilt. */
-inline constexpr std::uint32_t kCacheFormatVersion = 67;
+inline constexpr std::uint32_t kCacheFormatVersion = 68;
 /** Signed -1 on disk means there is no equipment slot. */
 inline constexpr std::int8_t kAbsentEquipmentSlot = -1;
 /** The standard 64-bit FNV-1a offset basis starts the payload checksum. */
@@ -622,9 +622,9 @@ struct RewardPoolRecord {
 struct RewardEntryRecord {
     std::uint16_t itemIndex{};
     std::uint16_t poolIndex{};
+    std::uint16_t mappingIndex{};
     std::uint32_t quantity{};
     std::uint32_t categoryHash{};
-    std::uint32_t bucketHash{};
     float weight{};
     RewardRangeRecord condition{};
     RewardRangeRecord modifiers{};
@@ -654,7 +654,7 @@ static_assert(sizeof(RewardSelectionRecord) == 2 * sizeof(std::uint32_t));
 static_assert(sizeof(RewardRangeRecord) == 2 * sizeof(std::uint32_t));
 static_assert(sizeof(RewardPoolRecord) == sizeof(std::uint32_t) + sizeof(RewardRangeRecord));
 static_assert(sizeof(RewardEntryRecord)
-              == 2 * sizeof(std::uint16_t) + 3 * sizeof(std::uint32_t) + sizeof(float)
+              == 3 * sizeof(std::uint16_t) + 2 * sizeof(std::uint32_t) + sizeof(float)
                      + 3 * sizeof(RewardRangeRecord));
 static_assert(sizeof(RewardItemRecord)
               == 2 * sizeof(std::uint32_t) + 2 * sizeof(std::uint16_t) + sizeof(std::uint8_t)

+ 1 - 1
Sunrise/src/state/build_data/rewards/definition.h

@@ -69,9 +69,9 @@ struct Modifier {
 struct Entry {
     std::uint16_t itemIndex{kAbsent};
     std::uint16_t poolIndex{kAbsent};
+    std::uint16_t mappingIndex{kAbsent};
     std::uint32_t quantity{};
     std::uint32_t categoryHash{};
-    std::uint32_t bucketHash{};
     float weight{};
     Range condition{};
     Range modifiers{};

+ 8 - 5
Sunrise/src/state/rewards/reward_resolver.cpp

@@ -225,6 +225,10 @@ struct Resolver {
         if (value == 0) {
             return true;
         }
+        // A mapping can accompany an item or nested pool; all effects belong to the grant.
+        if (entry.mappingIndex != definitions::kAbsent) {
+            return refuse(context, "reward_mapping");
+        }
         if (entry.poolIndex != definitions::kAbsent) {
             double total = 0;
             if (!pool_weight(entry.poolIndex, category, depth + 1, total)) {
@@ -238,7 +242,7 @@ struct Resolver {
                 return false;
             }
         } else {
-            return refuse(context, "reward_mapping");
+            return refuse(context, "reward_target");
         }
         output = value;
         return true;
@@ -266,10 +270,8 @@ struct Resolver {
         return std::isfinite(total);
     }
 
-    bool draw(std::uint16_t index,
-              std::uint32_t category,
-              std::size_t depth,
-              double total) noexcept {
+    bool
+    draw(std::uint16_t index, std::uint32_t category, std::size_t depth, double total) noexcept {
         const auto range = data.pools[index].entries;
         double remaining = fraction() * total;
         const definitions::Entry* chosen = nullptr;
@@ -291,6 +293,7 @@ struct Resolver {
             return refuse(context, "empty_pool");
         }
         if (chosen->poolIndex != definitions::kAbsent) {
+            // A pool reference selects one leaf; quantity belongs to that leaf.
             double childTotal = 0;
             return pool_weight(chosen->poolIndex, category, depth + 1, childTotal) && childTotal > 0
                    && draw(chosen->poolIndex, category, depth + 1, childTotal);

+ 1 - 1
Sunrise/src/state/runtime/state_account_reward_grant_runtime.cpp

@@ -377,7 +377,7 @@ bool preview_reward_unlocks(const PendingRecordRewardGrant& mutation,
     return true;
 }
 
-/** Revalidates the native draw under the same lock that commits its inventory and flags. */
+/** Revalidates the prepared reward under the lock that commits its inventory and flags. */
 bool commit_season_pass_reward(PendingSeasonPassReward& mutation) noexcept {
     if (!mutation.prepared) {
         return false;