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

Return-To-The-Roots / libsiedler2 / 14537997660

18 Apr 2025 04:06PM UTC coverage: 81.697% (-0.3%) from 82.012%
14537997660

push

github

Flamefire
Require Boost 1.73

An undefined `PTHREAD_STACK_MIN` causes a compile failure otherwise.

5200 of 6365 relevant lines covered (81.7%)

4237.22 hits per line

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

82.83
/src/ArchivItem_Map_Header.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 "ArchivItem_Map_Header.h"
6
#include "ErrorCodes.h"
7
#include "fileFormatHelpers.h"
8
#include "oem.h"
9
#include "libendian/EndianIStreamAdapter.h"
10
#include "libendian/EndianOStreamAdapter.h"
11
#include <array>
12
#include <iostream>
13
#include <stdexcept>
14

15
/** @class libsiedler2::ArchivItem_Map_Header
16
 *
17
 *  Klasse für einen Mapheader.
18
 */
19

20
const char VALID_ID[11] = "WORLD_V1.0";
21

22
libsiedler2::ArchivItem_Map_Header::ArchivItem_Map_Header() : ArchivItem(BobType::MapHeader) {}
6✔
23

24
libsiedler2::ArchivItem_Map_Header::~ArchivItem_Map_Header() = default;
25

26
/**
27
 *  lädt den Mapheader aus einer Datei.
28
 *
29
 *  @param[in] file Dateihandle der Datei
30
 *
31
 *  @return liefert Null bei Erfolg, ungleich Null bei Fehler
32
 */
33
int libsiedler2::ArchivItem_Map_Header::load(std::istream& file)
4✔
34
{
35
    if(!file)
4✔
36
        return ErrorCode::FILE_NOT_ACCESSIBLE;
×
37

38
    std::array<char, 10> id;
39

40
    libendian::EndianIStreamAdapter<false, std::istream&> fs(file);
4✔
41
    // Signatur einlesen
42
    fs >> id;
4✔
43

44
    // und prüfen
45
    if(!fs || !isChunk(id, VALID_ID))
4✔
46
        return ErrorCode::WRONG_HEADER;
×
47

48
    // Read name. Either 20B + width/height (2B each) or 24B
49
    // Ignore it for now and come back later
50
    long namePos = fs.getPosition();
4✔
51
    fs.setPositionRel(20);
4✔
52
    uint16_t posWidth, posHeight;
53
    fs >> posWidth >> posHeight;
4✔
54

55
    fs >> gfxset >> numPlayers;
4✔
56

57
    // 20B, should include nullptr
58
    std::array<char, 21> author;
59
    fs.readRaw(author.data(), 20);
4✔
60
    author.back() = '\0';
4✔
61
    this->author_ = OemToAnsi(author.data());
4✔
62

63
    fs >> playerHQx >> playerHQy;
4✔
64

65
    fs >> isInvalid; // This should be checked, but it seems some editors wrongly leave it set
4✔
66

67
    fs >> playerFaces >> areaInfos;
4✔
68

69
    uint16_t headerSig;
70
    fs >> headerSig;
4✔
71
    if(headerSig == 0) // On the map "Das Dreieck" there are 2 extra bytes here. This is a bug in the map!
4✔
72
    {
73
        fs >> headerSig;
1✔
74
        hasExtraWord_ = true;
1✔
75
    } else
76
        hasExtraWord_ = false;
3✔
77
    if(headerSig != 0x2711)
4✔
78
        return ErrorCode::WRONG_FORMAT;
×
79

80
    uint32_t unknown; // Might be switch for int16_t or long header blocks in WORLD#.DAT files
81
    fs >> unknown;
4✔
82
    assert(unknown == 0);
4✔
83

84
    fs >> width >> height;
4✔
85

86
    // What name format do we have?
87
    size_t nameLen;
88
    if(width == posWidth && height == posHeight)
4✔
89
        nameLen = 20;
3✔
90
    else
91
        nameLen = 24;
1✔
92
    long curPos = fs.getPosition();
4✔
93
    fs.setPosition(namePos);
4✔
94
    // It should include a nullptr terminator, but we have to make sure
95
    std::array<char, 25> name;
96
    fs.readRaw(name.data(), nameLen);
4✔
97
    name[nameLen] = '\0';
4✔
98
    fs.setPosition(curPos);
4✔
99

100
    setName(OemToAnsi(name.data()));
4✔
101

102
    return (!file) ? ErrorCode::UNEXPECTED_EOF : ErrorCode::NONE;
4✔
103
}
104

105
/**
106
 *  schreibt den Mapheader in eine Datei.
107
 *
108
 *  @param[in] file Dateihandle der Datei
109
 *
110
 *  @return liefert Null bei Erfolg, ungleich Null bei Fehler
111
 */
112
int libsiedler2::ArchivItem_Map_Header::write(std::ostream& file) const
5✔
113
{
114
    if(!file)
5✔
115
        return ErrorCode::FILE_NOT_ACCESSIBLE;
×
116

117
    libendian::EndianOStreamAdapter<false, std::ostream&> fs(file);
5✔
118
    // Signatur
119
    std::array<char, 10> id;
120
    setChunkId(id, VALID_ID);
5✔
121
    fs << id;
5✔
122

123
    // Name einlesen
124
    std::string tmpName = AnsiToOem(getName().substr(0, 23));
10✔
125
    std::array<char, 24> name;
126
    std::copy(tmpName.begin(), tmpName.end(), name.begin());
5✔
127
    std::fill(name.begin() + tmpName.length(), name.end(), '\0');
5✔
128
    fs << name;
5✔
129
    // Actual map name length is only 20 bytes. The width and height is used for unlimited play only to display the size
130
    // We use it if the name (including trailing zero) fit into this space, otherwise we overwrite the size with the map
131
    // name
132
    if(tmpName.length() < 20)
5✔
133
    {
134
        fs.setPositionRel(-4);
3✔
135
        fs << width << height;
3✔
136
    }
137

138
    fs << gfxset << numPlayers;
5✔
139

140
    // Autor einlesen
141
    tmpName = AnsiToOem(author_.substr(0, 19));
5✔
142
    std::array<char, 20> author;
143
    std::copy(tmpName.begin(), tmpName.end(), author.begin());
5✔
144
    std::fill(author.begin() + tmpName.length(), author.end(), '\0');
5✔
145
    fs << author << playerHQx << playerHQy;
5✔
146

147
    fs << isInvalid; // This should be checked, but it seems some editors wrongly leave it set
5✔
148

149
    fs << playerFaces << areaInfos;
5✔
150

151
    // Header sig
152
    fs << uint16_t(0x2711) << uint32_t(0);
5✔
153

154
    // Breite einlesen
155
    fs << width;
5✔
156

157
    // Höhe einlesen
158
    fs << height;
5✔
159

160
    return (!file) ? ErrorCode::UNEXPECTED_EOF : ErrorCode::NONE;
5✔
161
}
162

163
/**
164
 *  liefert die Breite der Map.
165
 */
166
uint16_t libsiedler2::ArchivItem_Map_Header::getWidth() const
84✔
167
{
168
    return width;
84✔
169
}
170

171
/**
172
 *  setzt die Breite der Map.
173
 *
174
 *  @param[in] width Breite der Map
175
 */
176
void libsiedler2::ArchivItem_Map_Header::setWidth(uint16_t width)
1✔
177
{
178
    this->width = width;
1✔
179
}
1✔
180

181
/**
182
 *  liefert die Höhe der Map.
183
 */
184
uint16_t libsiedler2::ArchivItem_Map_Header::getHeight() const
80✔
185
{
186
    return height;
80✔
187
}
188

189
/**
190
 *  setzt die Höhe der Map.
191
 *
192
 *  @param[in] height Höhe der Map
193
 */
194
void libsiedler2::ArchivItem_Map_Header::setHeight(uint16_t height)
1✔
195
{
196
    this->height = height;
1✔
197
}
1✔
198

199
/**
200
 *  liefert das GfxSet der Map.
201
 */
202
uint8_t libsiedler2::ArchivItem_Map_Header::getGfxSet() const
×
203
{
204
    return gfxset;
×
205
}
206

207
/**
208
 *  setzt das GfxSet der Map.
209
 *
210
 *  @param[in] gfxset GfxSet der Map
211
 */
212
void libsiedler2::ArchivItem_Map_Header::setGfxSet(uint8_t gfxset)
1✔
213
{
214
    this->gfxset = gfxset;
1✔
215
}
1✔
216

217
/**
218
 *  liefert die Spielerzahl der Map.
219
 */
220
uint8_t libsiedler2::ArchivItem_Map_Header::getNumPlayers() const
×
221
{
222
    return numPlayers;
×
223
}
224

225
/**
226
 *  setzt die Spielerzahl der Map.
227
 *
228
 *  @param[in] player Spielerzahl der Map
229
 */
230
void libsiedler2::ArchivItem_Map_Header::setNumPlayers(uint8_t numPlayers)
1✔
231
{
232
    this->numPlayers = numPlayers;
1✔
233
}
1✔
234

235
/**
236
 *  liefert den Autor der Map.
237
 */
238
const std::string& libsiedler2::ArchivItem_Map_Header::getAuthor() const
×
239
{
240
    return author_;
×
241
}
242

243
/**
244
 *  setzt den Autor der Map.
245
 *
246
 *  @param[in] author Autor der Map
247
 */
248
void libsiedler2::ArchivItem_Map_Header::setAuthor(const std::string& author)
1✔
249
{
250
    this->author_ = author;
1✔
251
}
1✔
252

253
/**
254
 * Sets position of the headquarter for the specified player.
255
 *
256
 * @param player player number (0-6)
257
 * @param x x-coordinate of the headquarter
258
 * @param y y-coordinate of the headquarter
259
 */
260
void libsiedler2::ArchivItem_Map_Header::setPlayerHQ(const uint32_t player, const uint16_t x, const uint16_t y)
4✔
261
{
262
    if(player >= playerHQx.size())
4✔
263
        throw std::range_error("Only " + std::to_string(maxPlayers) + " players allowed!");
×
264
    playerHQx[player] = x;
4✔
265
    playerHQy[player] = y;
4✔
266
}
4✔
267

268
/**
269
 * Gets position of the headquarter for the specified player.
270
 *
271
 * @param player player number (0-6)
272
 * @param[out] x x-coordinate of the headquarter
273
 * @param[out] y y-coordinate of the headquarter
274
 */
275
void libsiedler2::ArchivItem_Map_Header::getPlayerHQ(const uint32_t player, uint16_t& x, uint16_t& y) const
×
276
{
277
    if(player >= playerHQx.size())
×
278
        throw std::range_error("Only " + std::to_string(maxPlayers) + " players allowed!");
×
279
    x = playerHQx[player];
×
280
    y = playerHQy[player];
×
281
}
×
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