| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // Regression for the selected-state arrival window.
- //
- // An authored region is `sliceSetIndex + stateOrdinal`. Ember's apex gameplay and both ending
- // bookends are sibling states of slice set 0 (regions 0, 1 and 2), while every earlier area is
- // its own slice set. Only a slice-set change replaces the client's instantiated world.
- //
- // Treating a sibling move as a replacement is what froze the mission's ending: the roster
- // withheld region 1's groups until the client reported holding region 1, and the client's
- // current region leg only advances on a real slice-set switch, so the report never came.
- #include <cassert>
- #include <cstdint>
- #include "../Sunrise/src/server/bap/encrypted/push/activity/mission_seed_world_change.h"
- namespace {
- namespace seed = sunrise::server::bap::encrypted::push::activity;
- /** Ember's authored states, as `{sliceSetIndex, effectiveRegion}`. */
- constexpr std::uint32_t kApexSliceSet = 0;
- constexpr std::uint32_t kApexRegion = 0;
- constexpr std::uint32_t kFirstMovieRegion = 1;
- constexpr std::uint32_t kSecondMovieRegion = 2;
- constexpr std::uint32_t kArrivalSliceSet = 48;
- constexpr std::uint32_t kArrivalRegion = 49;
- constexpr std::uint32_t kPowerhouseSliceSet = 64;
- constexpr std::uint32_t kPowerhouseRegion = 64;
- constexpr std::uint32_t kLinkSliceSet = 56;
- constexpr std::uint32_t kLinkRegion = 56;
- constexpr std::uint32_t kCinderSliceSet = 40;
- constexpr std::uint32_t kCinderRegion = 40;
- void sibling_states_keep_their_world() {
- // Apex gameplay to the first ending bookend: same slice set, so nothing is rebuilt.
- assert(!seed::mission_seed_region_change_replaces_world(
- kApexSliceSet, kApexRegion, kApexSliceSet, kFirstMovieRegion));
- // First bookend to the second: still slice set 0.
- assert(!seed::mission_seed_region_change_replaces_world(
- kApexSliceSet, kFirstMovieRegion, kApexSliceSet, kSecondMovieRegion));
- // And back, so a checkpoint or reselection is treated the same way.
- assert(!seed::mission_seed_region_change_replaces_world(
- kApexSliceSet, kSecondMovieRegion, kApexSliceSet, kApexRegion));
- }
- void slice_set_changes_replace_the_world() {
- // Every transition the mission already made is a real slice-set change and must stay one,
- // or the roster would register the new region's groups into a world being torn down.
- assert(seed::mission_seed_region_change_replaces_world(
- kArrivalSliceSet, kArrivalRegion, kPowerhouseSliceSet, kPowerhouseRegion));
- assert(seed::mission_seed_region_change_replaces_world(
- kPowerhouseSliceSet, kPowerhouseRegion, kLinkSliceSet, kLinkRegion));
- assert(seed::mission_seed_region_change_replaces_world(
- kLinkSliceSet, kLinkRegion, kCinderSliceSet, kCinderRegion));
- assert(seed::mission_seed_region_change_replaces_world(
- kCinderSliceSet, kCinderRegion, kApexSliceSet, kApexRegion));
- // Backtracking is a replacement in both directions.
- assert(seed::mission_seed_region_change_replaces_world(
- kCinderSliceSet, kCinderRegion, kLinkSliceSet, kLinkRegion));
- }
- void reselecting_the_same_state_is_never_a_replacement() {
- assert(!seed::mission_seed_region_change_replaces_world(
- kApexSliceSet, kApexRegion, kApexSliceSet, kApexRegion));
- assert(!seed::mission_seed_region_change_replaces_world(
- kCinderSliceSet, kCinderRegion, kCinderSliceSet, kCinderRegion));
- // A same-region selection stays a no-op even if the slice sets disagree: the region is the
- // publication key, and re-registering identical groups must not reopen an arrival window.
- assert(!seed::mission_seed_region_change_replaces_world(
- kApexSliceSet, kApexRegion, kCinderSliceSet, kApexRegion));
- }
- void decision_is_available_at_compile_time() {
- // The production caller is in a lock-held path, so the predicate must fold away.
- static_assert(!seed::mission_seed_region_change_replaces_world(0, 0, 0, 1));
- static_assert(seed::mission_seed_region_change_replaces_world(40, 40, 0, 0));
- }
- void arrival_window_closes_when_no_arrival_can_be_reported() {
- constexpr std::uint32_t factor = 8;
- // Ember's ending: apex gameplay held, region 1 pending, both slice set 0. No slice-set switch
- // happens, so the client never reports region 1 and the window must close on its own.
- assert(seed::mission_seed_arrival_window_closed(kApexRegion, kFirstMovieRegion,
- kApexSliceSet, factor));
- assert(seed::mission_seed_arrival_window_closed(kFirstMovieRegion, kSecondMovieRegion,
- kApexSliceSet, factor));
- // The ordinary case still closes on the arrival itself.
- assert(seed::mission_seed_arrival_window_closed(kPowerhouseRegion, kPowerhouseRegion,
- kPowerhouseSliceSet, factor));
- }
- void arrival_window_stays_open_across_a_real_slice_set_change() {
- constexpr std::uint32_t factor = 8;
- // Holding Cinder while Apex is pending is a genuine teardown: the window must stay open or
- // the publication registers the new region's groups into the world being torn down.
- assert(!seed::mission_seed_arrival_window_closed(kCinderRegion, kApexRegion,
- kApexSliceSet, factor));
- assert(!seed::mission_seed_arrival_window_closed(kPowerhouseRegion, kLinkRegion,
- kLinkSliceSet, factor));
- // Holding nothing yet is not an arrival.
- assert(!seed::mission_seed_arrival_window_closed(-1, kApexRegion, kApexSliceSet, factor));
- // A zero factor would make the slice-set test meaningless; it must not close the window.
- assert(!seed::mission_seed_arrival_window_closed(kApexRegion, kFirstMovieRegion,
- kApexSliceSet, 0));
- }
- } // namespace
- int main() {
- // Real full-mission case: the last explicit seed is the landing, but ordinary
- // traversal already brought the player to Apex before selecting its ending.
- assert(!seed::mission_seed_selection_needs_arrival(64, 64, 0, 1, 0, 8));
- assert(!seed::mission_seed_selection_needs_arrival(0, 1, 0, 2, 0, 8));
- assert(seed::mission_seed_selection_needs_arrival(64, 64, 0, 1, 64, 8));
- assert(seed::mission_seed_selection_needs_arrival(64, 64, 0, 1, -1, 8));
- sibling_states_keep_their_world();
- slice_set_changes_replace_the_world();
- reselecting_the_same_state_is_never_a_replacement();
- decision_is_available_at_compile_time();
- arrival_window_closes_when_no_arrival_can_be_reported();
- arrival_window_stays_open_across_a_real_slice_set_change();
- return 0;
- }
|