1 /*
2 * Copyright (C) 2002-2020 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20 #include "map_io/map_allowed_building_types_packet.h"
21
22 #include "base/macros.h"
23 #include "io/profile.h"
24 #include "logic/game.h"
25 #include "logic/game_data_error.h"
26 #include "logic/map_objects/tribes/tribe_descr.h"
27 #include "logic/player.h"
28
29 namespace Widelands {
30
31 constexpr int32_t kCurrentPacketVersion = 1;
32
read(FileSystem & fs,EditorGameBase & egbase,bool const skip,MapObjectLoader &)33 void MapAllowedBuildingTypesPacket::read(FileSystem& fs,
34 EditorGameBase& egbase,
35 bool const skip,
36 MapObjectLoader&) {
37 if (skip) {
38 return;
39 }
40
41 Profile prof;
42 try {
43 prof.read("allowed_building_types", nullptr, fs);
44 } catch (const WException&) {
45 try {
46 prof.read("allowed_buildings", nullptr, fs);
47 } catch (...) {
48 return;
49 }
50 } catch (...) {
51 return;
52 }
53 try {
54 int32_t const packet_version = prof.get_safe_section("global").get_safe_int("packet_version");
55 if (packet_version == kCurrentPacketVersion) {
56 PlayerNumber const nr_players = egbase.map().get_nrplayers();
57 upcast(Game const, game, &egbase);
58
59 // Now read all players and buildings.
60 iterate_players_existing(p, nr_players, egbase, player) {
61
62 const TribeDescr& tribe = player->tribe();
63 // All building types default to false in the game (not in the
64 // editor).
65 if (game) {
66 for (DescriptionIndex i = 0; i < game->tribes().nrbuildings(); ++i) {
67 player->allow_building_type(i, false);
68 }
69 }
70 try {
71 Section& s = prof.get_safe_section(
72 (boost::format("player_%u") % static_cast<unsigned int>(p)).str());
73
74 bool allowed;
75 while (const char* const name = s.get_next_bool(nullptr, &allowed)) {
76 const DescriptionIndex index = tribe.building_index(name);
77 if (tribe.has_building(index)) {
78 player->allow_building_type(index, allowed);
79 } else {
80 log("WARNING: MapAllowedBuildingTypesPacket - tribe %s does not define "
81 "building type \"%s\"\n",
82 tribe.name().c_str(), name);
83 }
84 }
85 } catch (const WException& e) {
86 throw GameDataError("player %u (%s): %s", p, tribe.name().c_str(), e.what());
87 }
88 }
89 } else {
90 throw UnhandledVersionError(
91 "MapAllowedBuildingTypesPacket", packet_version, kCurrentPacketVersion);
92 }
93 } catch (const WException& e) {
94 throw GameDataError("allowed buildings: %s", e.what());
95 }
96 }
97
write(FileSystem & fs,EditorGameBase & egbase,MapObjectSaver &)98 void MapAllowedBuildingTypesPacket::write(FileSystem& fs, EditorGameBase& egbase, MapObjectSaver&) {
99 Profile prof;
100 prof.create_section("global").set_int("packet_version", kCurrentPacketVersion);
101
102 PlayerNumber const nr_players = egbase.map().get_nrplayers();
103 iterate_players_existing_const(p, nr_players, egbase, player) {
104 const TribeDescr& tribe = player->tribe();
105 const std::string section_key =
106 (boost::format("player_%u") % static_cast<unsigned int>(p)).str();
107 Section& section = prof.create_section(section_key.c_str());
108
109 // Write for all buildings if it is enabled.
110 for (const Widelands::DescriptionIndex& building_index : tribe.buildings()) {
111 if (player->is_building_type_allowed(building_index)) {
112 const BuildingDescr* building_descr =
113 egbase.tribes().get_building_descr(building_index);
114 section.set_bool(building_descr->name().c_str(), true);
115 }
116 }
117 }
118
119 prof.write("allowed_building_types", false, fs);
120 }
121 } // namespace Widelands
122