mission_script_runtime_region.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #include <cstdint>
  2. #include <string_view>
  3. #include "../../../state/activity/destination/activity_destination_spawn_binding.h"
  4. #include "../../../state/activity/membership/activity_membership_query.h"
  5. #include "../../../state/build_data/runtime.h"
  6. #include "../../bap/runtime.h"
  7. #include "mission_script_runtime_internal.h"
  8. namespace sunrise::server::activity::mission {
  9. /**
  10. * Moves the client to the region a freshly selected mission state belongs to.
  11. * The client picks its object registry from the loaded slice-set entry, so a state in another
  12. * region has no findable objects until it transitions. Message 12 is the only mid-activity move.
  13. * @param instance Runtime instance whose state selection just published.
  14. * @param plan Published plan naming the target region and its bubble.
  15. */
  16. void arm_state_region_teleport(RuntimeInstance& instance,
  17. const server::bap::ActivityMissionSeedPlan& plan) noexcept {
  18. namespace membership = ::sunrise::state::activity::membership;
  19. const auto& destination = instance.view.binding.destination;
  20. if (destination.packageNameLength == 0
  21. || destination.packageNameLength > destination.packageName.size()
  22. || plan.effectiveRegion > static_cast<std::uint32_t>(membership::kMaximumSliceSetIndex)) {
  23. return;
  24. }
  25. const std::int32_t reported = membership::player_region(instance.view.binding.sessionId);
  26. // A sibling-state transition still needs the host teleport to order the spawn.
  27. if (reported == static_cast<std::int32_t>(plan.effectiveRegion)) {
  28. // Already there. Clear any earlier arm so the mirror owns the block again.
  29. static_cast<void>(membership::arm_host_teleport(
  30. instance.view.binding.sessionId, membership::kAbsentSliceSetIndex, 0));
  31. return;
  32. }
  33. namespace dest = ::sunrise::state::activity::destination;
  34. // The move carries the spawn set the client filters its spawn points by, not a slice-set name.
  35. // A set answers only the slice sets of the bubble that declares it; the empty-name hash
  36. // elsewhere leaves the client on `default`, the set a launch into this region uses.
  37. const auto target = static_cast<std::uint16_t>(plan.effectiveRegion);
  38. const std::uint32_t declared = membership::declared_spawn_set(instance.view.binding.sessionId);
  39. const bool declaredAnswers =
  40. declared != 0 && dest::spawn_set_slice_set(destination, declared, target) == target;
  41. const bool armed =
  42. membership::arm_host_teleport(instance.view.binding.sessionId,
  43. static_cast<std::int32_t>(plan.effectiveRegion),
  44. declaredAnswers ? declared : dest::kAbsentSpawnSetHash);
  45. log_line(core::log::Level::info,
  46. &instance,
  47. "state_region",
  48. armed ? "teleport_armed" : "teleport_unchanged");
  49. }
  50. } // namespace sunrise::server::activity::mission