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_object_saver.h"
21
22 #include "base/wexception.h"
23 #include "economy/ferry_fleet.h"
24 #include "economy/flag.h"
25 #include "economy/portdock.h"
26 #include "economy/road.h"
27 #include "economy/ship_fleet.h"
28 #include "economy/ware_instance.h"
29 #include "economy/waterway.h"
30 #include "logic/map_objects/bob.h"
31 #include "logic/map_objects/tribes/battle.h"
32 #include "logic/map_objects/tribes/building.h"
33
34 namespace Widelands {
35
MapObjectSaver()36 MapObjectSaver::MapObjectSaver()
37 : nr_roads_(0),
38 nr_waterways_(0),
39 nr_flags_(0),
40 nr_buildings_(0),
41 nr_bobs_(0),
42 nr_wares_(0),
43 nr_immovables_(0),
44 nr_battles_(0),
45 nr_ship_fleets_(0),
46 nr_ferry_fleets_(0),
47 nr_portdocks_(0),
48 lastserial_(0) {
49 }
50
51 /**
52 * Return a pointer to the record for the given object.
53 * Create a record if that hasn't been done yet.
54 */
get_object_record(const MapObject & obj)55 MapObjectSaver::MapObjectRec& MapObjectSaver::get_object_record(const MapObject& obj) {
56 MapObjectRecordMap::iterator it = objects_.find(&obj);
57
58 if (it != objects_.end()) {
59 return it->second;
60 }
61
62 MapObjectRec rec;
63 #ifndef NDEBUG
64 rec.description = to_string(obj.descr().type());
65 rec.description += " (";
66 rec.description += obj.serial();
67 rec.description += ')';
68 #endif
69 rec.fileserial = ++lastserial_;
70 rec.registered = false;
71 rec.saved = false;
72 return objects_.insert(std::pair<MapObject const*, MapObjectRec>(&obj, rec)).first->second;
73 }
74
75 /**
76 * Returns true if this object has already been registered.
77 * \deprecated since get_object_file_index supports unregistered objects now
78 */
is_object_known(const MapObject & obj) const79 bool MapObjectSaver::is_object_known(const MapObject& obj) const {
80 MapObjectRecordMap::const_iterator it = objects_.find(&obj);
81
82 if (it == objects_.end()) {
83 return false;
84 }
85
86 return it->second.registered;
87 }
88
is_object_saved(const MapObject & obj)89 bool MapObjectSaver::is_object_saved(const MapObject& obj) {
90 return get_object_record(obj).saved;
91 }
92
93 /*
94 * Registers this object as a new one
95 */
register_object(const MapObject & obj)96 Serial MapObjectSaver::register_object(const MapObject& obj) {
97 MapObjectRec& rec = get_object_record(obj);
98
99 assert(!rec.registered);
100
101 if (dynamic_cast<Flag const*>(&obj)) {
102 ++nr_flags_;
103 } else if (dynamic_cast<Road const*>(&obj)) {
104 ++nr_roads_;
105 } else if (dynamic_cast<Waterway const*>(&obj)) {
106 ++nr_waterways_;
107 } else if (dynamic_cast<Building const*>(&obj)) {
108 ++nr_buildings_;
109 } else if (dynamic_cast<Immovable const*>(&obj)) {
110 ++nr_immovables_;
111 } else if (dynamic_cast<WareInstance const*>(&obj)) {
112 ++nr_wares_;
113 } else if (dynamic_cast<Bob const*>(&obj)) {
114 ++nr_bobs_;
115 } else if (dynamic_cast<Battle const*>(&obj)) {
116 ++nr_battles_;
117 } else if (dynamic_cast<ShipFleet const*>(&obj)) {
118 ++nr_ship_fleets_;
119 } else if (dynamic_cast<FerryFleet const*>(&obj)) {
120 ++nr_ferry_fleets_;
121 } else if (dynamic_cast<PortDock const*>(&obj)) {
122 ++nr_portdocks_;
123 } else {
124 throw wexception("MapObjectSaver: Unknown MapObject type");
125 }
126
127 rec.registered = true;
128 return rec.fileserial;
129 }
130
131 /**
132 * Returns the file index for this map object. This is used on load
133 * to regenerate the dependencies between the objects.
134 */
get_object_file_index(const MapObject & obj)135 uint32_t MapObjectSaver::get_object_file_index(const MapObject& obj) {
136 return get_object_record(obj).fileserial;
137 }
138
139 /**
140 * Returns the file index of the given object, or zero for null pointers.
141 */
get_object_file_index_or_zero(const MapObject * obj)142 uint32_t MapObjectSaver::get_object_file_index_or_zero(const MapObject* obj) {
143 if (obj) {
144 return get_object_file_index(*obj);
145 }
146 return 0;
147 }
148
149 /*
150 * mark this object as saved
151 */
mark_object_as_saved(const MapObject & obj)152 void MapObjectSaver::mark_object_as_saved(const MapObject& obj) {
153 MapObjectRec& rec = get_object_record(obj);
154 assert(rec.registered);
155 rec.saved = true;
156 }
157
158 #ifndef NDEBUG
159 /*
160 * Return the number of unsaved objects
161 */
detect_unsaved_objects() const162 void MapObjectSaver::detect_unsaved_objects() const {
163 for (const auto& temp_map : objects_) {
164 if (!temp_map.second.saved) {
165 throw wexception("%s has not been saved", temp_map.second.description.c_str());
166 }
167 }
168 }
169 #endif
170 } // namespace Widelands
171