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

Return-To-The-Roots / s25client / 15703316495

17 Jun 2025 09:20AM UTC coverage: 50.448% (-0.02%) from 50.467%
15703316495

push

github

web-flow
Merge pull request #1534 from tehKaiN/portrait-support

Add support for player/nation portraits

58 of 162 new or added lines in 17 files covered. (35.8%)

23 existing lines in 5 files now uncovered.

22505 of 44610 relevant lines covered (50.45%)

35490.83 hits per line

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

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

5
#include "SavedFile.h"
6
#include "BasePlayerInfo.h"
7
#include "RTTR_Version.h"
8
#include "enum_cast.hpp"
9
#include "libendian/ConvertEndianess.h"
10
#include "s25util/BinaryFile.h"
11
#include "s25util/Serializer.h"
12
#include <boost/format.hpp>
13
#include <algorithm>
14
#include <mygettext/mygettext.h>
15
#include <stdexcept>
16

17
SavedFile::SavedFile() : saveTime_(0)
18✔
18
{
19
    const std::string rev = rttr::version::GetRevision();
18✔
20
    std::copy(rev.begin(), rev.begin() + revision.size(), revision.begin());
18✔
21
}
18✔
22

23
SavedFile::~SavedFile() = default;
18✔
24

25
uint8_t SavedFile::GetMinorVersion() const
27✔
26
{
27
    return minorVersion_.value();
27✔
28
}
29

NEW
30
uint8_t SavedFile::GetMajorVersion() const
×
31
{
NEW
32
    return majorVersion_.value();
×
33
}
34

35
void SavedFile::WriteFileHeader(BinaryFile& file) const
7✔
36
{
37
    // Signature
38
    const std::string signature = GetSignature();
14✔
39
    file.WriteRawData(signature.c_str(), signature.length());
7✔
40
    // Format version
41
    file.WriteUnsignedChar(GetLatestMajorVersion());
7✔
42
    file.WriteUnsignedChar(GetLatestMinorVersion());
7✔
43
}
7✔
44

45
void SavedFile::WriteExtHeader(BinaryFile& file, const std::string& mapName)
6✔
46
{
47
    // Store data in struct
48
    saveTime_ = s25util::Time::CurrentTime();
6✔
49
    mapName_ = mapName;
6✔
50

51
    // Program version
52
    file.WriteRawData(revision.data(), revision.size());
6✔
53
    s25util::time64_t tmpTime = libendian::ConvertEndianess<false>::fromNative(saveTime_);
6✔
54
    file.WriteRawData(&tmpTime, sizeof(tmpTime));
6✔
55
    file.WriteShortString(mapName);
6✔
56
    file.WriteUnsignedInt(playerNames_.size());
6✔
57
    for(const std::string& name : playerNames_)
24✔
58
        file.WriteShortString(name);
18✔
59
}
6✔
60

61
bool SavedFile::ReadFileHeader(BinaryFile& file)
12✔
62
{
63
    lastErrorMsg.clear();
12✔
64

65
    const std::string signature = GetSignature();
24✔
66
    std::array<char, 32> read_signature;
67
    if(signature.size() > read_signature.size())
12✔
68
        throw std::range_error("Program signature is to long!");
×
69
    try
70
    {
71
        file.ReadRawData(read_signature.data(), signature.size());
12✔
72

73
        // Signatur überprüfen
74
        if(!std::equal(signature.begin(), signature.end(), read_signature.begin()))
12✔
75
        {
76
            lastErrorMsg = _("File is not in a valid format!");
×
77
            return false;
×
78
        }
79

80
        // Version überprüfen
81
        majorVersion_ = file.ReadUnsignedChar();
12✔
82
        minorVersion_ = file.ReadUnsignedChar();
12✔
83
        if(majorVersion_ != GetLatestMajorVersion() || minorVersion_ > GetLatestMinorVersion())
12✔
84
        {
85
            boost::format fmt =
NEW
86
              boost::format((majorVersion_ < GetLatestMajorVersion()) ?
×
NEW
87
                              _("File has an old version and cannot be used (version: %1%.%2%, expected: %3%.%4%)!") :
×
NEW
88
                              _("File was created with more recent program and cannot be used (version: %1%.%2%, "
×
NEW
89
                                "expected: %3%.%4%)!"));
×
90
            lastErrorMsg =
NEW
91
              (fmt % majorVersion_.value() % minorVersion_.value() % GetLatestMajorVersion() % GetLatestMinorVersion())
×
NEW
92
                .str();
×
UNCOV
93
            return false;
×
94
        }
95
    } catch(const std::runtime_error& e)
×
96
    {
97
        lastErrorMsg = e.what();
×
98
        return false;
×
99
    }
100

101
    return true;
12✔
102
}
103

104
bool SavedFile::ReadExtHeader(BinaryFile& file)
10✔
105
{
106
    file.ReadRawData(revision.data(), revision.size());
10✔
107
    file.ReadRawData(&saveTime_, sizeof(saveTime_));
10✔
108
    saveTime_ = libendian::ConvertEndianess<false>::toNative(saveTime_);
10✔
109
    mapName_ = file.ReadShortString();
10✔
110
    playerNames_.resize(file.ReadUnsignedInt());
10✔
111
    for(std::string& name : playerNames_)
40✔
112
        name = file.ReadShortString();
30✔
113
    return true;
10✔
114
}
115

116
void SavedFile::WriteAllHeaderData(BinaryFile& file, const std::string& mapName)
6✔
117
{
118
    // Versionszeug schreiben
119
    WriteFileHeader(file);
6✔
120
    WriteExtHeader(file, mapName);
6✔
121
}
6✔
122

123
bool SavedFile::ReadAllHeaderData(BinaryFile& file)
10✔
124
{
125
    if(!ReadFileHeader(file))
10✔
126
        return false;
×
127
    if(!ReadExtHeader(file))
10✔
128
        return false;
×
129
    return true;
10✔
130
}
131

132
void SavedFile::WritePlayerData(BinaryFile& file)
6✔
133
{
134
    Serializer ser;
12✔
135
    ser.PushUnsignedChar(players.size());
6✔
136
    for(const auto& player : players)
29✔
137
        player.Serialize(ser, true);
23✔
138

139
    ser.WriteToFile(file);
6✔
140
}
6✔
141

142
void SavedFile::ReadPlayerData(BinaryFile& file)
7✔
143
{
144
    ClearPlayers();
7✔
145
    Serializer ser;
14✔
146
    ser.ReadFromFile(file);
7✔
147
    const unsigned playerCt = ser.PopUnsignedChar();
7✔
148
    players.reserve(playerCt);
7✔
149
    for(unsigned i = 0; i < playerCt; i++)
34✔
150
    {
151
        // TODO(Replay) TODO(Savegame) minor versions will change their meaning when major is bumped
152
        BasePlayerInfo player(ser, GetMinorVersion() >= 1 ? 1 : 0, true);
54✔
153
        // Temporary workaround: The random team was stored in the file but should not anymore, see PR #1331
154
        if(player.team > Team::Team4)
27✔
155
            player.team = Team(rttr::enum_cast(player.team) - 3); // Was random team 2-4
×
156
        else if(player.team == Team::Random)
27✔
157
            player.team = Team::Team1; // Was random team 1
×
158
        AddPlayer(player);
27✔
159
    }
160
}
7✔
161

162
/**
163
 *  schreibt die GlobalGameSettings in die Datei.
164
 */
165
void SavedFile::WriteGGS(BinaryFile& file) const
6✔
166
{
167
    Serializer ser;
12✔
168
    ggs.Serialize(ser);
6✔
169
    ser.WriteToFile(file);
6✔
170
}
6✔
171

172
/**
173
 *  liest die GlobalGameSettings aus der Datei.
174
 */
175
void SavedFile::ReadGGS(BinaryFile& file)
7✔
176
{
177
    Serializer ser;
14✔
178
    ser.ReadFromFile(file);
7✔
179
    ggs.Deserialize(ser);
7✔
180
}
7✔
181

182
const BasePlayerInfo& SavedFile::GetPlayer(unsigned idx) const
27✔
183
{
184
    return players[idx];
27✔
185
}
186

187
unsigned SavedFile::GetNumPlayers()
9✔
188
{
189
    return players.size();
9✔
190
}
191

192
void SavedFile::AddPlayer(const BasePlayerInfo& player)
50✔
193
{
194
    players.push_back(player);
50✔
195
    if(player.isUsed())
50✔
196
        playerNames_.push_back(player.name);
39✔
197
}
50✔
198

199
void SavedFile::ClearPlayers()
17✔
200
{
201
    players.clear();
17✔
202
    playerNames_.clear();
17✔
203
}
17✔
204

205
std::string SavedFile::GetRevision() const
×
206
{
207
    return std::string(revision.begin(), revision.end());
×
208
}
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