Skip to content

Commit 3e39f0d

Browse files
committed
support overlapping moves
1 parent 6677c72 commit 3e39f0d

File tree

9 files changed

+120
-14
lines changed

9 files changed

+120
-14
lines changed

src/display/mapcanvas.cpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -660,16 +660,7 @@ void MapCanvas::mouseMoveEvent(QMouseEvent *const event)
660660
auto &map = this->m_data;
661661
auto isMovable = [&map](RoomSelection &sel, const Coordinate &offset) -> bool {
662662
sel.removeMissing(map);
663-
for (const RoomId id : sel) {
664-
const Coordinate &here = map.getRoomHandle(id).getPosition();
665-
const Coordinate target = here + offset;
666-
if (const auto &other = map.findRoomHandle(target)) {
667-
if (!sel.contains(other.getId())) {
668-
return false;
669-
}
670-
}
671-
}
672-
return true;
663+
return map.getCurrentMap().wouldAllowRelativeMove(sel.getRoomIds(), offset);
673664
};
674665

675666
const auto diff = getSel2().pos.truncate() - getSel1().pos.truncate();
@@ -823,10 +814,8 @@ void MapCanvas::mouseReleaseEvent(QMouseEvent *const event)
823814
m_roomSelectionMove.reset();
824815
if (!wrongPlace && (m_roomSelection != nullptr)) {
825816
const Coordinate moverel{pos, 0};
826-
m_data.applyChangesToList(
827-
*m_roomSelection, [&moverel](const RawRoom &room) -> Change {
828-
return Change{room_change_types::MoveRelative{room.getId(), moverel}};
829-
});
817+
m_data.applySingleChange(Change{
818+
room_change_types::MoveRelative2{m_roomSelection->getRoomIds(), moverel}});
830819
}
831820

832821
} else {

src/map/ChangePrinter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,18 @@ void ChangePrinter::print(const RoomFieldVariant &var)
561561
#undef X_NOP
562562
}
563563

564+
void ChangePrinter::print(const RoomIdSet &set)
565+
{
566+
auto prefix = "";
567+
m_os << "RoomIdSet{";
568+
for (auto id : set) {
569+
m_os << prefix;
570+
prefix = ", ";
571+
print(id);
572+
}
573+
m_os << "}";
574+
}
575+
564576
void ChangePrinter::print(const ParseEvent &event)
565577
{
566578
BEGIN_STRUCT_HELPER("ParseEvent")
@@ -663,6 +675,15 @@ void ChangePrinter::virt_accept(const MoveRelative &change)
663675
}
664676
}
665677

678+
void ChangePrinter::virt_accept(const MoveRelative2 &change)
679+
{
680+
BEGIN_STRUCT_HELPER("MoveRelative2")
681+
{
682+
HELPER_ADD_MEMBER(rooms);
683+
HELPER_ADD_MEMBER(offset);
684+
}
685+
}
686+
666687
void ChangePrinter::virt_accept(const TryMoveCloseTo &change)
667688
{
668689
BEGIN_STRUCT_HELPER("TryMoveCloseTo")

src/map/ChangePrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ struct NODISCARD ChangePrinter final : public AbstractChangeVisitor
8888
void print(const ExitFieldVariant &var);
8989
void print(const RoomFieldVariant &var);
9090

91+
private:
92+
void print(const RoomIdSet &set);
93+
9194
private:
9295
void print(const ParseEvent &ev);
9396

src/map/ChangeTypes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ struct NODISCARD MoveRelative final
101101
Coordinate offset;
102102
};
103103

104+
struct NODISCARD MoveRelative2 final
105+
{
106+
RoomIdSet rooms;
107+
Coordinate offset;
108+
};
109+
104110
struct NODISCARD MergeRelative final
105111
{
106112
RoomId room = INVALID_ROOMID;
@@ -261,6 +267,8 @@ struct NODISCARD ConnectToNeighborsArgs final
261267
SEP() \
262268
X(room_change_types::MoveRelative) \
263269
SEP() \
270+
X(room_change_types::MoveRelative2) \
271+
SEP() \
264272
X(room_change_types::RemoveRoom) \
265273
SEP() \
266274
X(room_change_types::SetServerId) \

src/map/Map.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,11 @@ void Map::foreachChangedRoom(ProgressCounter &pc,
10781078
}
10791079
}
10801080

1081+
NODISCARD bool Map::wouldAllowRelativeMove(const RoomIdSet &set, const Coordinate &offset) const
1082+
{
1083+
return getWorld().wouldAllowRelativeMove(set, offset);
1084+
}
1085+
10811086
BasicDiffStats getBasicDiffStats(const Map &baseMap, const Map &modMap)
10821087
{
10831088
const auto &base = baseMap.getWorld();

src/map/Map.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ class NODISCARD Map final
140140
const Map &saved,
141141
const Map &current,
142142
const std::function<void(const RawRoom &room)> &callback);
143+
144+
public:
145+
NODISCARD bool wouldAllowRelativeMove(const RoomIdSet &set, const Coordinate &offset) const;
143146
};
144147

145148
struct NODISCARD MapApplyResult final

src/map/World.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
844864
void 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+
849913
void 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+
16721742
void World::apply(ProgressCounter & /*pc*/, const room_change_types::MergeRelative &change)
16731743
{
16741744
//

src/map/World.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class NODISCARD World final
216216

217217
private:
218218
void moveRelative(RoomId id, const Coordinate &offset);
219+
void moveRelative(const RoomIdSet &rooms, const Coordinate &offset);
219220
void setPosition(RoomId id, const Coordinate &coord);
220221
void setServerId(RoomId id, ServerRoomId serverId);
221222

@@ -280,4 +281,7 @@ class NODISCARD World final
280281

281282
private:
282283
NODISCARD bool containsRoomsNotIn(const World &other) const;
284+
285+
public:
286+
NODISCARD bool wouldAllowRelativeMove(const RoomIdSet &set, const Coordinate &offset) const;
283287
};

src/mapdata/roomselection.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class NODISCARD RoomSelection final : public std::enable_shared_from_this<RoomSe
4747
void erase(RoomId targetId) { m_set.erase(targetId); }
4848
void clear() { m_set = {}; }
4949

50+
public:
51+
NODISCARD const RoomIdSet &getRoomIds() const { return m_set; }
52+
5053
public:
5154
void removeMissing(MapData &mapData);
5255

0 commit comments

Comments
 (0)