1- // Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org)
1+ // Copyright (C) 2005 - 2026 Settlers Freaks (sf-team at siedler25.org)
22//
33// SPDX-License-Identifier: GPL-2.0-or-later
44
77#include " Game.h"
88#include " SerializedGameData.h"
99#include " buildings/noBuildingSite.h"
10+ #include " helpers/IdRange.h"
1011#include " helpers/Range.h"
1112#include " lua/GameDataLoader.h"
1213#include " world/GameWorldBase.h"
1314#include " s25util/warningSuppression.h"
15+ #include < boost/container/static_vector.hpp>
1416#include < mygettext/mygettext.h>
1517
1618void MapSerializer::Serialize (const GameWorldBase& world, SerializedGameData& sgd)
@@ -49,6 +51,7 @@ void MapSerializer::Serialize(const GameWorldBase& world, SerializedGameData& sg
4951 for (const auto & c : curNeighbors)
5052 {
5153 sgd.PushUnsignedInt (c.id .value ());
54+ sgd.PushUnsignedInt (c.sea .value ());
5255 sgd.PushUnsignedInt (c.distance );
5356 }
5457 }
@@ -147,8 +150,11 @@ void MapSerializer::Deserialize(GameWorldBase& world, SerializedGameData& sgd, G
147150 {
148151 RTTR_UNUSED (j);
149152 const auto id = HarborId (sgd.PopUnsignedInt ());
153+ SeaId sea;
154+ if (sgd.GetGameDataVersion () >= 15 )
155+ sea = SeaId (sgd.PopUnsignedInt ());
150156 const auto distance = sgd.PopUnsignedInt ();
151- neighbor.emplace_back (id, distance);
157+ neighbor.emplace_back (id, sea, distance);
152158 }
153159 }
154160 }
@@ -158,6 +164,56 @@ void MapSerializer::Deserialize(GameWorldBase& world, SerializedGameData& sgd, G
158164 if (!world.harborData .front ().pos .isValid ())
159165 world.harborData .erase (world.harborData .begin ());
160166 }
167+ if (sgd.GetGameDataVersion () < 15 )
168+ {
169+ const auto getSeas = [&world](const HarborId& hbId) {
170+ boost::container::static_vector<SeaId, helpers::NumEnumValues_v<Direction>> seas;
171+ for (const auto sea : world.harborData [hbId].seaIds )
172+ {
173+ if (sea)
174+ seas.push_back (sea);
175+ }
176+ return seas;
177+ };
178+ // Determine seas for neighbors
179+ for (const auto startHbId : helpers::idRange<HarborId>(world.GetNumHarborPoints ()))
180+ {
181+ const auto mySeas = getSeas (startHbId);
182+ for (auto & neighborsPerDir : world.harborData [startHbId].neighbors )
183+ {
184+ for (auto & neighbor : neighborsPerDir)
185+ {
186+ // Easy case: Either harbor is only at a single sea, so that must be the one
187+ if (mySeas.size () == 1u )
188+ {
189+ neighbor.sea = mySeas.front ();
190+ continue ;
191+ }
192+ const auto otherSeas = getSeas (neighbor.id );
193+ if (otherSeas.size () == 1u )
194+ {
195+ neighbor.sea = otherSeas.front ();
196+ continue ;
197+ }
198+ // Find the sea where this distance matches
199+ for (const auto sea : mySeas)
200+ {
201+ if (!helpers::contains (otherSeas, sea))
202+ continue ;
203+ unsigned len;
204+ if (world.FindShipPath (world.GetCoastalPoint (startHbId, sea),
205+ world.GetCoastalPoint (neighbor.id , sea), neighbor.distance , nullptr , &len)
206+ && len == neighbor.distance )
207+ {
208+ neighbor.sea = sea;
209+ break ;
210+ }
211+ }
212+ RTTR_Assert (neighbor.sea );
213+ }
214+ }
215+ }
216+ }
161217
162218 sgd.PopObjectContainer (world.harbor_building_sites_from_sea , GO_Type::Buildingsite);
163219
0 commit comments