@@ -841,11 +841,75 @@ void World::setPosition(const RoomId id, const Coordinate &coord)
841841 m_rooms.setPosition (id, coord);
842842}
843843
844+ bool World::wouldAllowRelativeMove (const RoomIdSet &rooms, const Coordinate &offset) const
845+ {
846+ if (rooms.empty ()) {
847+ return false ;
848+ }
849+ for (const auto id : rooms) {
850+ if (!hasRoom (id)) {
851+ return false ; // avoid throwing
852+ }
853+ const auto &here = getPosition (id); // throws if missing
854+ const auto there = here + offset;
855+ if (auto other = findRoom (there)) {
856+ if (!rooms.contains (*other)) {
857+ return false ;
858+ }
859+ }
860+ }
861+ return true ;
862+ }
863+
844864void World::moveRelative (const RoomId id, const Coordinate &offset)
845865{
846866 setPosition (id, getPosition (id) + offset);
847867}
848868
869+ void World::moveRelative (const RoomIdSet &rooms, const Coordinate &offset)
870+ {
871+ if (rooms.empty ()) {
872+ throw std::runtime_error (" no rooms specified" );
873+ }
874+
875+ if (!wouldAllowRelativeMove (rooms, offset)) {
876+ throw std::runtime_error (" invalid batch movement" );
877+ }
878+
879+ volatile bool use_hack = false ;
880+ if (use_hack) {
881+ // This isn't advised, since it doesn't handle potential signed integer under/overflow.
882+ int zimpossible = 1 ;
883+ if (auto bounds = getBounds ()) {
884+ zimpossible = std::max (0 , bounds->max .z - bounds->min .z ) + 1 ;
885+ }
886+ qInfo () << " zimpossible = " << zimpossible;
887+ for (const auto id : rooms) {
888+ moveRelative (id, Coordinate{0 , 0 , -zimpossible});
889+ }
890+ for (const auto id : rooms) {
891+ moveRelative (id, offset + Coordinate{0 , 0 , zimpossible});
892+ }
893+ } else {
894+ struct NODISCARD MoveInfo final
895+ {
896+ RoomId id;
897+ Coordinate newPos;
898+ };
899+ std::vector<MoveInfo> infos;
900+ infos.reserve (rooms.size ());
901+ for (const auto id : rooms) {
902+ const auto &oldPos = getPosition (id);
903+ infos.emplace_back (MoveInfo{id, oldPos + offset});
904+ m_spatialDb.remove (id, oldPos);
905+ }
906+ for (const auto &x : infos) {
907+ m_spatialDb.add (x.id , x.newPos );
908+ m_rooms.setPosition (x.id , x.newPos );
909+ }
910+ }
911+ }
912+
849913void World::updateRoom (const RawRoom &newRoom)
850914{
851915 const RoomId id = newRoom.id ;
@@ -1669,6 +1733,12 @@ void World::apply(ProgressCounter & /*pc*/, const room_change_types::MoveRelativ
16691733 moveRelative (change.room , change.offset );
16701734}
16711735
1736+ void World::apply (ProgressCounter & /* pc*/ , const room_change_types::MoveRelative2 &change)
1737+ {
1738+ //
1739+ moveRelative (change.rooms , change.offset );
1740+ }
1741+
16721742void World::apply (ProgressCounter & /* pc*/ , const room_change_types::MergeRelative &change)
16731743{
16741744 //
0 commit comments