• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Return-To-The-Roots / s25client / 22773697264

06 Mar 2026 05:07PM UTC coverage: 50.323%. First build
22773697264

Pull #1901

github

web-flow
Merge 0b0ec6b90 into 8a6c9b6f2
Pull Request #1901: Introduce strong types for sea and harbor ids

216 of 287 new or added lines in 23 files covered. (75.26%)

23045 of 45794 relevant lines covered (50.32%)

42956.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.35
/libs/s25main/world/MapSerializer.cpp
1
// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "world/MapSerializer.h"
6
#include "CatapultStone.h"
7
#include "Game.h"
8
#include "SerializedGameData.h"
9
#include "buildings/noBuildingSite.h"
10
#include "helpers/Range.h"
11
#include "lua/GameDataLoader.h"
12
#include "world/GameWorldBase.h"
13
#include "s25util/warningSuppression.h"
14
#include <mygettext/mygettext.h>
15

16
void MapSerializer::Serialize(const GameWorldBase& world, SerializedGameData& sgd)
6✔
17
{
18
    // Headinformationen
19
    helpers::pushPoint(sgd, world.GetSize());
6✔
20
    sgd.PushString(world.GetDescription().get(world.GetLandscapeType()).name);
6✔
21

22
    sgd.PushUnsignedInt(GameObject::GetObjIDCounter());
6✔
23

24
    // Alle Weltpunkte serialisieren
25
    const unsigned numPlayers = world.GetNumPlayers();
6✔
26
    for(const auto& node : world.nodes)
5,366✔
27
    {
28
        node.Serialize(sgd, numPlayers, world.GetDescription());
5,360✔
29
    }
30

31
    // Katapultsteine serialisieren
32
    sgd.PushObjectContainer(world.catapult_stones, true);
6✔
33
    // Meeresinformationen serialisieren
34
    sgd.PushUnsignedInt(world.seas.size());
6✔
35
    for(const auto& sea : world.seas)
6✔
36
    {
37
        sgd.PushUnsignedInt(sea.nodes_count);
×
38
    }
39
    // Hafenpositionen serialisieren
40
    sgd.PushUnsignedInt(world.harbor_pos.size());
6✔
41
    for(const auto& curHarborPos : world.harbor_pos)
6✔
42
    {
43
        helpers::pushPoint(sgd, curHarborPos.pos);
×
44
        helpers::pushContainer(sgd, curHarborPos.seaIds);
×
45
        for(const auto& curNeighbors : curHarborPos.neighbors)
×
46
        {
47
            sgd.PushUnsignedInt(curNeighbors.size());
×
48

49
            for(const auto& c : curNeighbors)
×
50
            {
NEW
51
                sgd.PushUnsignedInt(c.id.value());
×
52
                sgd.PushUnsignedInt(c.distance);
×
53
            }
54
        }
55
    }
56

57
    sgd.PushObjectContainer(world.harbor_building_sites_from_sea, true);
6✔
58

59
    if(!world.HasLua())
6✔
60
        sgd.PushLongString("");
4✔
61
    else
62
    {
63
        sgd.PushLongString(world.GetLua().getScript());
2✔
64
        Serializer luaSaveState;
4✔
65
        try
66
        {
67
            if(!world.GetLua().Serialize(luaSaveState))
2✔
68
                throw SerializedGameData::Error(_("Failed to save lua state!"));
×
69
        } catch(const std::exception& e)
×
70
        {
71
            throw SerializedGameData::Error(std::string(_("Failed to save lua state!")) + _("Error: ") + e.what());
×
72
        }
73
        sgd.PushUnsignedInt(0xC0DEBA5E); // Start Lua identifier
2✔
74
        sgd.PushUnsignedInt(luaSaveState.GetLength());
2✔
75
        sgd.PushRawData(luaSaveState.GetData(), luaSaveState.GetLength());
2✔
76
        sgd.PushUnsignedInt(0xC001C0DE); // End Lua identifier
2✔
77
    }
78
}
6✔
79

80
void MapSerializer::Deserialize(GameWorldBase& world, SerializedGameData& sgd, Game& game,
3✔
81
                                ILocalGameState& localgameState)
82
{
83
    // Initialisierungen
84
    GameDataLoader gdLoader(world.GetDescriptionWriteable());
6✔
85
    if(!gdLoader.Load())
3✔
86
        throw SerializedGameData::Error(_("Failed to load game data!"));
×
87

88
    // Headinformationen
89
    const auto size = helpers::popPoint<MapExtent>(sgd);
3✔
90
    DescIdx<LandscapeDesc> lt;
3✔
91
    if(sgd.GetGameDataVersion() < 3)
3✔
92
    {
93
        uint8_t gfxSet = sgd.PopUnsignedChar();
×
94
        lt = world.GetDescription().landscapes.find([gfxSet](const LandscapeDesc& l) { return l.s2Id == gfxSet; });
×
95
    } else
96
    {
97
        std::string sLandscape = sgd.PopString();
6✔
98
        lt = world.GetDescription().landscapes.getIndex(sLandscape);
3✔
99
        if(!lt)
3✔
100
            throw SerializedGameData::Error(std::string("Invalid landscape: ") + sLandscape);
×
101
    }
102
    world.Init(size, lt);
3✔
103
    GameObject::ResetCounters(sgd.PopUnsignedInt());
3✔
104

105
    std::vector<DescIdx<TerrainDesc>> landscapeTerrains;
6✔
106
    if(sgd.GetGameDataVersion() < 3)
3✔
107
    {
108
        // Assumes the order of the terrain in the description file is the same as in the prior RTTR versions
109
        landscapeTerrains =
110
          world.GetDescription().terrain.findAll([lt](const TerrainDesc& t) { return t.landscape == lt; });
×
111
    }
112
    // Alle Weltpunkte
113
    MapPoint curPos(0, 0);
3✔
114
    const unsigned numPlayers = world.GetNumPlayers();
3✔
115
    for(auto& node : world.nodes)
2,683✔
116
    {
117
        node.Deserialize(sgd, numPlayers, world.GetDescription(), landscapeTerrains);
2,680✔
118
        curPos.x++;
2,680✔
119
        if(curPos.x >= world.GetWidth())
2,680✔
120
        {
121
            curPos.x = 0;
74✔
122
            curPos.y++;
74✔
123
        }
124
    }
125

126
    // Katapultsteine deserialisieren
127
    sgd.PopObjectContainer(world.catapult_stones, GO_Type::Catapultstone);
3✔
128

129
    // Meeresinformationen deserialisieren
130
    world.seas.resize(sgd.PopUnsignedInt());
3✔
131
    for(auto& sea : world.seas)
3✔
132
    {
133
        sea.nodes_count = sgd.PopUnsignedInt();
×
134
    }
135

136
    // Hafenpositionen serialisieren
137
    const unsigned numHarborPositions = sgd.PopUnsignedInt();
3✔
138
    world.harbor_pos.clear();
3✔
139
    world.harbor_pos.reserve(numHarborPositions);
3✔
140
    for(const auto i : helpers::range<unsigned>(numHarborPositions))
12✔
141
    {
142
        RTTR_UNUSED(i);
143
        world.harbor_pos.emplace_back(sgd.PopMapPoint());
×
144
        auto& curHarborPos = world.harbor_pos.back();
×
145
        helpers::popContainer(sgd, curHarborPos.seaIds);
×
146
        for(auto& neighbor : curHarborPos.neighbors)
×
147
        {
148
            const unsigned numNeighbors = sgd.PopUnsignedInt();
×
149
            neighbor.reserve(numNeighbors);
×
150
            for(const auto j : helpers::range<unsigned>(numNeighbors))
×
151
            {
152
                RTTR_UNUSED(j);
NEW
153
                const auto id = HarborId(sgd.PopUnsignedInt());
×
154
                const auto distance = sgd.PopUnsignedInt();
×
155
                neighbor.emplace_back(id, distance);
×
156
            }
157
        }
158
    }
159
    if(sgd.GetGameDataVersion() < 13 && !world.harbor_pos.empty())
3✔
NEW
160
        world.harbor_pos.erase(world.harbor_pos.begin());
×
161

162
    sgd.PopObjectContainer(world.harbor_building_sites_from_sea, GO_Type::Buildingsite);
3✔
163

164
    const std::string luaScript = sgd.PopLongString();
6✔
165
    if(!luaScript.empty())
3✔
166
    {
167
        if(sgd.PopUnsignedInt() != 0xC0DEBA5E)
1✔
168
            throw SerializedGameData::Error(_("Invalid id for lua data"));
×
169
        // If there is a script, there is also save data. Store reference to that
170
        const auto luaSaveSize = sgd.PopUnsignedInt();
1✔
171
        Serializer luaSaveState(sgd.PopAndDiscard(luaSaveSize), luaSaveSize);
2✔
172
        if(sgd.PopUnsignedInt() != 0xC001C0DE)
1✔
173
            throw SerializedGameData::Error(_("Invalid end-id for lua data"));
×
174

175
        // Now init and load lua
176
        auto lua = std::make_unique<LuaInterfaceGame>(game, localgameState);
1✔
177
        if(!lua->loadScriptString(luaScript))
1✔
178
            throw SerializedGameData::Error(_("Lua script failed to load."));
×
179
        if(!lua->CheckScriptVersion())
1✔
180
            throw SerializedGameData::Error(_("Wrong version for lua script."));
×
181
        try
182
        {
183
            if(!lua->Deserialize(luaSaveState))
1✔
184
                throw SerializedGameData::Error(_("Lua load callback returned failure!"));
×
185
        } catch(const std::exception& e)
×
186
        {
187
            throw SerializedGameData::Error(std::string(_("Failed to load lua state!")) + _("Error: ") + e.what());
×
188
        }
189
        game.SetLua(std::move(lua));
1✔
190
    }
191
    world.CreateTradeGraphs();
3✔
192
}
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc