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 #ifndef WL_MAP_IO_MAP_OBJECT_LOADER_H
21 #define WL_MAP_IO_MAP_OBJECT_LOADER_H
22 
23 #include "base/macros.h"
24 #include "logic/game_data_error.h"
25 #include "logic/map_objects/map_object.h"
26 
27 namespace Widelands {
28 class Bob;
29 
30 /*
31  * This class helps to
32  *   - keep track of map objects on the map (to be loaded)
33  *   - translate file index pointers into MapObjects
34  */
35 class MapObjectLoader {
36 public:
37 	bool is_object_known(uint32_t) const;
38 
39 	/// Registers the object as a new one.
40 	///
41 	/// \returns a reference to the object.
42 	/// \throws WException if there is already an object registered with the
43 	/// same serial. (not implemented: In that case, the object is deleted.)
44 	///
45 	// TODO(unknown): Currently the object must be passed as a parameter to this
46 	// function. This should be changed so that the object is allocated here.
47 	// The parameter object should then be removed and the function renamed to
48 	// create_object. Then there will no longer be necessary to delete the
49 	// object in case the serial number is alrealy known, since the object will
50 	// never even be allocated then. But this change can only be done when all
51 	// kinds of map objects have suitable default constructors.
register_object(Serial const n,T & object)52 	template <typename T> T& register_object(Serial const n, T& object) {
53 		ReverseMapObjectMap::const_iterator const existing = objects_.find(n);
54 		if (existing != objects_.end()) {
55 			// delete &object; can not do this
56 			throw GameDataError(
57 			   "already loaded (%s)", to_string(existing->second->descr().type()).c_str());
58 		}
59 		objects_.insert(std::pair<Serial, MapObject*>(n, &object));
60 		loaded_objects_[&object] = false;
61 		return object;
62 	}
63 
get(Serial const serial)64 	template <typename T> T& get(Serial const serial) {
65 		ReverseMapObjectMap::iterator const it = objects_.find(serial);
66 		if (it == objects_.end())
67 			throw GameDataError("not found");
68 		else if (upcast(T, result, it->second))
69 			return *result;
70 		else
71 			throw GameDataError("is a %s, expected a %s",
72 			                    to_string(it->second->descr().type()).c_str(), typeid(T).name());
73 	}
74 
75 	int32_t get_nr_unloaded_objects();
is_object_loaded(MapObject & obj)76 	bool is_object_loaded(MapObject& obj) {
77 		return loaded_objects_[&obj];
78 	}
79 
80 	void mark_object_as_loaded(MapObject&);
81 
82 	void schedule_destroy(MapObject&);
83 	void schedule_act(Bob&);
84 
85 	void load_finish_game(Game& g);
86 
87 	// TODO(Nordfriese): This is one exceedingly ugly hack for savegame compatibiliy.
88 	Serial get_economy_savegame_compatibility(Serial ware_economy) const;
89 
90 private:
91 	using ReverseMapObjectMap = std::map<Serial, MapObject*>;
92 
93 	std::map<MapObject*, bool> loaded_objects_;
94 	ReverseMapObjectMap objects_;
95 
96 	std::vector<MapObject*> schedule_destroy_;
97 	std::vector<Bob*> schedule_act_;
98 };
99 }  // namespace Widelands
100 
101 #endif  // end of include guard: WL_MAP_IO_MAP_OBJECT_LOADER_H
102