26 return absl::FailedPreconditionError(
"Track document is unavailable");
28 return absl::OkStatus();
30 const uint64_t generation = panel->track_generation();
31 std::optional<size_t> sprite_index;
32 std::optional<zelda3::Sprite> old_sprite, new_sprite;
35 return absl::InvalidArgumentError(
36 "Move a start within its existing room");
39 return absl::FailedPreconditionError(
"Load the start room first");
43 old_sprite = room->GetSprites()[index];
45 for (
size_t other = 0; other < room->GetSprites().size(); ++other) {
46 const auto& sprite = room->GetSprites()[other];
47 if (other != index && !sprite.deleted() && sprite.id() == 0xA3 &&
48 sprite.layer() == 0 && sprite.x() * 16 == local.first &&
49 sprite.y() * 16 == local.second)
50 return absl::FailedPreconditionError(
"Another cart occupies this stop");
52 new_sprite.emplace(old_sprite->id(), local.first / 16, local.second / 16,
53 old_sprite->subtype(), old_sprite->layer());
54 new_sprite->set_key_drop(old_sprite->key_drop());
55 new_sprite->set_deleted(old_sprite->deleted());
56 auto candidates = room->GetSprites();
57 candidates[index] = *new_sprite;
60 auto restore = [
this, generation, before, after, sprite_index, old_sprite,
61 new_sprite](
bool forward) -> absl::Status {
64 return absl::FailedPreconditionError(
"Track document closed");
65 const auto& expected = forward ? before : after;
66 const auto& replacement = forward ? after : before;
70 if (!room || *sprite_index >= room->
GetSprites().size())
71 return absl::FailedPreconditionError(
72 "The paired cart is no longer loaded");
73 const auto& current = room->
GetSprites()[*sprite_index];
74 const auto& wanted = forward ? *old_sprite : *new_sprite;
75 if (current.id() != wanted.id() || current.x() != wanted.x() ||
76 current.y() != wanted.y() || current.subtype() != wanted.subtype() ||
77 current.layer() != wanted.layer() ||
78 current.deleted() != wanted.deleted() ||
79 current.key_drop() != wanted.key_drop())
80 return absl::FailedPreconditionError(
81 "The paired cart changed; repeat the edit");
84 current_panel->RestoreTrackDraft(generation, expected, replacement));
86 room->
GetSprites()[*sprite_index] = forward ? *new_sprite : *old_sprite;
88 current_panel->MarkPairedTrackDraft();
92 return absl::OkStatus();
96 return absl::OkStatus();