Jelajahi Sumber

Stop granting records the account never earned

Seeding claimed a real chapter in every lore book so that books gated on their
own progress would show a title. That is a permanent state change to records
written into the claim file, and it is not this build's to make: a record should
be claimed because the account earned it.

The visibility gates stay. Those satisfy a category's unlock expression and
grant nothing; the seeding was the only part that authored records.
Millie 2 minggu lalu
induk
melakukan
90011fccb0

+ 0 - 8
Sunrise/src/middleware/datagen/family4/account/account_encoder.cpp

@@ -100,14 +100,6 @@ bool encode(const state::AccountState& state, std::span<std::byte> output) noexc
     object.acquiredFlags = unlocks.accountFlags;
     // Claims arrive after boot, so they cannot be in the authored policy. Lay them over the
     // bank here, which is the one place every Family-4 account image passes through.
-    // Seeded once the node and record tables are up, which is why it hangs off the image rather
-    // than startup. Latches, so a run whose books are already open pays nothing.
-    static std::atomic<bool> loreSeeded{false};
-    if (!loreSeeded.load(std::memory_order_relaxed)
-        && state::build_data::nodes::count() != 0) {
-        (void)state::record_claims::seed_lore_visibility();
-        loreSeeded.store(true, std::memory_order_relaxed);
-    }
     (void)state::record_claims::apply(object.acquiredFlags);
     // Lore book categories are gated on a flag they cannot set by being played: with no title shown
     // there is nothing inside to claim, and nothing to claim leaves the gate shut.

+ 0 - 66
Sunrise/src/state/record_claims/record_claims.cpp

@@ -382,72 +382,6 @@ std::size_t apply_character_node_progress(std::span<std::int32_t> characterValue
     return written;
 }
 
-/** @return True when this index is already held. */
-bool claimed(std::uint16_t flagIndex) noexcept {
-    const std::lock_guard<std::mutex> guard(g_lock);
-    return claimed_locked(flagIndex);
-}
-
-/** Claims the first chapter of every lore book still showing a redacted title. */
-std::size_t seed_lore_visibility() noexcept {
-    namespace nodes = build_data::nodes;
-    std::vector<nodes::Definition> rows(nodes::kDefinitionCapacity);
-    std::size_t count = 0;
-    if (!nodes::snapshot(std::span<nodes::Definition>{rows}, count)) {
-        return 0;
-    }
-
-    std::size_t seeded = 0;
-    for (std::size_t row = 0; row < count; ++row) {
-        const nodes::Definition& node = rows[row];
-        if (node.definitionIndex < nodes::kLoreNodeFirst
-            || node.definitionIndex > nodes::kLoreNodeLast
-            || node.childCount == 0) {
-            continue;
-        }
-
-        // A book that already holds a claim is past its gate and is left as it is.
-        bool held = false;
-        for (std::size_t child = 0; child < node.childCount && !held; ++child) {
-            build_data::records::Definition record{};
-            if (build_data::find_record_definition(node.children[child], record)
-                && record.completionFlagIndex != build_data::records::kUnavailableFlagIndex) {
-                held = claimed(record.completionFlagIndex);
-            }
-        }
-        if (held) {
-            continue;
-        }
-
-        // Skip the first child: a book's first triumph is its parent, the one that counts the
-        // rest, and claiming it would not move the category's bar. Naming the parent by the slot it
-        // carries is not enough on its own, because that field resolves on only eleven records in
-        // the whole table, so position is what actually identifies it and the slot check backs it up.
-        for (std::size_t child = 1; child < node.childCount; ++child) {
-            build_data::records::Definition record{};
-            if (!build_data::find_record_definition(node.children[child], record)
-                || record.completionFlagIndex == build_data::records::kUnavailableFlagIndex
-                || (node.valueIndex != nodes::kUnavailableValueIndex
-                    && record.categoryValueIndex == node.valueIndex)) {
-                continue;
-            }
-            if (claim(record.completionFlagIndex, record.scoreValue)) {
-                ++seeded;
-            }
-            break;
-        }
-    }
-
-    std::array<char, 128> line{};
-    const int written = std::snprintf(
-        line.data(), line.size(), "ev=claims stage=lore_seed result=ok entries=%zu", seeded);
-    if (written > 0) {
-        core::log::write(core::log::Channel::state, core::log::Level::info,
-                         {line.data(), static_cast<std::size_t>(written)});
-    }
-    return seeded;
-}
-
 /** @return Total score of every held claim. */
 std::uint32_t total_score() noexcept {
     const std::lock_guard<std::mutex> guard(g_lock);

+ 1 - 14
Sunrise/src/state/record_claims/record_claims.h

@@ -57,22 +57,9 @@ std::size_t apply_node_progress(std::span<std::int32_t> objectiveValues) noexcep
 /** @return True when this index is already held. */
 [[nodiscard]] bool claimed(std::uint16_t flagIndex) noexcept;
 
-/**
- * Claims the first chapter of every lore book still showing a redacted title.
- *
- * These categories are gated on their own progress: the client shows no name until the value slot
- * their bar reads is above zero, and with no name there is nothing inside to claim, so the gate
- * cannot open by being played. Claiming one real chapter opens it. A real claim is used rather than
- * a written value so the flag, the score and the count stay in agreement, exactly as they would had
- * the chapter been claimed by hand. A book that already holds a claim is left alone.
- * @return Number of books seeded.
- */
-std::size_t seed_lore_visibility() noexcept;
-
 /**
  * Writes each category's claimed-child count into the character value slot its bar reads.
- * A category counting in the character bank has nowhere to put its count otherwise, and stays
- * redacted while every other book opens.
+ * One book counts in the character bank rather than the account one.
  * @param characterValues Character value bank, already filled from the authored policy.
  * @return Number of categories written.
  */