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_LOGIC_MAP_OBJECTS_MAP_OBJECT_H
21 #define WL_LOGIC_MAP_OBJECTS_MAP_OBJECT_H
22 
23 #include <boost/signals2/signal.hpp>
24 
25 #include "base/log.h"
26 #include "base/macros.h"
27 #include "graphic/animation/animation.h"
28 #include "graphic/animation/diranimations.h"
29 #include "graphic/color.h"
30 #include "graphic/image.h"
31 #include "logic/cmd_queue.h"
32 #include "logic/map_objects/info_to_draw.h"
33 #include "logic/map_objects/tribes/training_attribute.h"
34 #include "logic/widelands.h"
35 #include "scripting/lua_table.h"
36 
37 class RenderTarget;
38 
39 namespace Widelands {
40 
41 class MapObject;
42 class Player;
43 
44 // This enum lists the available classes of Map Objects.
45 enum class MapObjectType : uint8_t {
46 	MAPOBJECT = 0,  // Root superclass
47 
48 	WARE,  //  class WareInstance
49 	BATTLE,
50 	SHIP_FLEET,
51 	FERRY_FLEET,
52 
53 	BOB = 10,  // Bob
54 	CRITTER,   // Bob -- Critter
55 	SHIP,      // Bob -- Ship
56 	WORKER,    // Bob -- Worker
57 	CARRIER,   // Bob -- Worker -- Carrier
58 	SOLDIER,   // Bob -- Worker -- Soldier
59 	FERRY,     // Bob -- Worker -- Ferry
60 
61 	// everything below is at least a BaseImmovable
62 	IMMOVABLE = 30,
63 
64 	// everything below is at least a PlayerImmovable
65 	FLAG = 40,  // Flag
66 	PORTDOCK,   // Portdock
67 	ROADBASE,   // Roadbase
68 	ROAD,       // Roadbase -- Road
69 	WATERWAY,   // Roadbase -- Waterway
70 
71 	// everything below is at least a Building
72 	BUILDING = 100,    // Building
73 	CONSTRUCTIONSITE,  // Building -- Constructionsite
74 	DISMANTLESITE,     // Building -- Dismantlesite
75 	WAREHOUSE,         // Building -- Warehouse
76 	MARKET,            // Building -- Market
77 	PRODUCTIONSITE,    // Building -- Productionsite
78 	MILITARYSITE,      // Building -- Productionsite -- Militarysite
79 	TRAININGSITE       // Building -- Productionsite -- Trainingsite
80 };
81 
82 // Returns a string representation for 'type'.
83 std::string to_string(MapObjectType type);
84 
85 /**
86  * Base class for descriptions of worker, files and so on. This must just
87  * link them together
88  */
89 struct MapObjectDescr {
90 
91 	enum class OwnerType { kWorld, kTribe };
92 
93 	MapObjectDescr(const MapObjectType init_type,
94 	               const std::string& init_name,
95 	               const std::string& init_descname,
96 	               const std::string& init_helptext_script);
97 	MapObjectDescr(const MapObjectType init_type,
98 	               const std::string& init_name,
99 	               const std::string& init_descname,
100 	               const LuaTable& table);
101 	virtual ~MapObjectDescr();
102 
nameMapObjectDescr103 	const std::string& name() const {
104 		return name_;
105 	}
descnameMapObjectDescr106 	const std::string& descname() const {
107 		return descname_;
108 	}
109 
helptext_scriptMapObjectDescr110 	const std::string& helptext_script() const {
111 		return helptext_script_;
112 	}
113 
114 	// Type of the MapObjectDescr.
typeMapObjectDescr115 	MapObjectType type() const {
116 		return type_;
117 	}
118 
119 	virtual uint32_t get_animation(const std::string& animname, const MapObject* mo) const;
120 
121 	uint32_t main_animation() const;
122 	std::string get_animation_name(uint32_t) const;  ///< needed for save, debug
123 
124 	bool is_animation_known(const std::string& name) const;
125 
126 	/// Preload animation graphics at default scale
127 	void load_graphics() const;
128 
129 	/// Returns the image for the first frame of the idle animation if the MapObject has animations,
130 	/// nullptr otherwise
131 	const Image* representative_image(const RGBColor* player_color = nullptr) const;
132 
133 	/// Returns the menu image if the MapObject has one, nullptr otherwise
134 	const Image* icon() const;
135 	/// Returns the image fileneme for the menu image if the MapObject has one, is empty otherwise
136 	const std::string& icon_filename() const;
137 
138 	bool has_attribute(uint32_t) const;
139 	static uint32_t get_attribute_id(const std::string& name, bool add_if_not_exists = false);
140 
141 protected:
142 	// Add all the special attributes to the attribute list. Only the 'allowed_special'
143 	// attributes are allowed to appear - i.e. resi are fine for immovables.
144 	void add_attributes(const std::vector<std::string>& attributes,
145 	                    const std::set<uint32_t>& allowed_special);
146 	void add_attribute(uint32_t attr);
147 
148 	/// Sets the directional animations in 'anims' with the animations
149 	/// '&lt;basename&gt;_(ne|e|se|sw|w|nw)'.
150 	void assign_directional_animation(DirAnimations* anims, const std::string& basename);
151 
152 private:
153 	void add_animations(const LuaTable& table,
154 	                    const std::string& animation_directory,
155 	                    Animation::Type anim_type);
156 
157 	/// Throws an exception if the MapObjectDescr has no representative image
158 	void check_representative_image();
159 
160 	using Anims = std::map<std::string, uint32_t>;
161 	using AttribMap = std::map<std::string, uint32_t>;
162 	using Attributes = std::vector<uint32_t>;
163 
164 	const MapObjectType type_;    /// Subclasses pick from the enum above
165 	std::string const name_;      /// The name for internal reference
166 	std::string const descname_;  /// A localized Descriptive name
167 	/// The path and filename to the helptext script. Can be empty, but some subtypes like buildings,
168 	/// wares and workers require it.
169 	const std::string helptext_script_;
170 	Attributes attributes_;
171 	Anims anims_;
172 	static uint32_t dyn_attribhigh_;  ///< highest attribute ID used
173 	static AttribMap dyn_attribs_;
174 	std::string icon_filename_;  // Filename for the menu icon
175 
176 	DISALLOW_COPY_AND_ASSIGN(MapObjectDescr);
177 };
178 
179 /**
180  * \par Notes on MapObject
181  *
182  * MapObject is the base class for everything that can be on the map:
183  * buildings, animals, decorations, etc... most of the time, however, you'll
184  * deal with one of the derived classes, BaseImmovable or Bob.
185  *
186  * Every MapObject has a unique serial number. This serial number is used as
187  * key in the ObjectManager map, and in the safe ObjectPointer.
188  *
189  * Unless you're perfectly sure about when an object can be destroyed you
190  * should use an ObjectPointer or, better yet, the type safe OPtr template.
191  * This is not necessary when the relationship and lifetime between objects
192  * is well-defined, such as in the relationship between Building and Flag.
193  *
194  * MapObjects can also have attributes. They are mainly useful for finding
195  * objects of a given type (e.g. trees) within a certain radius.
196  *
197  * \warning DO NOT allocate/free MapObjects directly. Use the appropriate
198  * type-dependent create() function for creation, and call die() for removal.
199  *
200  * \note Convenient creation functions are defined in class Game.
201  *
202  * When you do create a new object yourself (i.e. when you're implementing one
203  * of the create() functions), you need to allocate the object using new,
204  * potentially set it up by calling basic functions like set_position(), etc.
205  * and then call init(). After that, the object is supposed to
206  * be fully created.
207  */
208 
209 /// If you find a better way to do this that doesn't cost a virtual function
210 /// or additional member variable, go ahead
211 #define MO_DESCR(type)                                                                             \
212 public:                                                                                            \
213 	const type& descr() const {                                                                     \
214 		return dynamic_cast<const type&>(*descr_);                                                   \
215 	}
216 
217 class MapObject {
218 	friend struct ObjectManager;
219 	friend struct ObjectPointer;
220 
221 	MO_DESCR(MapObjectDescr)
222 
223 public:
224 	/// Some default, globally valid, attributes.
225 	/// Other attributes (such as "harvestable corn") could be
226 	/// allocated dynamically (?)
227 	enum Attribute {
228 		CONSTRUCTIONSITE = 1,  ///< assume BUILDING
229 		WORKER,                ///< assume BOB
230 		SOLDIER,               ///<  assume WORKER
231 		RESI,                  ///<  resource indicator, assume IMMOVABLE
232 
233 		HIGHEST_FIXED_ATTRIBUTE
234 	};
235 
236 	struct LogSink {
237 		virtual void log(const std::string& str) = 0;
~LogSinkLogSink238 		virtual ~LogSink() {
239 		}
240 	};
241 
load_finish(EditorGameBase &)242 	virtual void load_finish(EditorGameBase&) {
243 	}
244 
245 	virtual const Image* representative_image() const;
246 
247 protected:
248 	explicit MapObject(MapObjectDescr const* descr);
~MapObject()249 	virtual ~MapObject() {
250 	}
251 
252 public:
serial()253 	Serial serial() const {
254 		return serial_;
255 	}
256 
257 	/**
258 	 * Is called right before the object will be removed from
259 	 * the game. No connection is handled in this class.
260 	 *
261 	 * param serial : the object serial (cannot use param comment as this is a callback)
262 	 */
263 	boost::signals2::signal<void(uint32_t serial)> removed;
264 
265 	/**
266 	 * Attributes are fixed boolean properties of an object.
267 	 * An object either has a certain attribute or it doesn't.
268 	 * See the \ref Attribute enume.
269 	 *
270 	 * \return whether this object has the given attribute
271 	 */
has_attribute(uint32_t const attr)272 	bool has_attribute(uint32_t const attr) const {
273 		return descr().has_attribute(attr);
274 	}
275 
276 	/**
277 	 * \return the value of the given \ref TrainingAttribute. -1 if this object
278 	 * doesn't have this kind of attribute.
279 	 * The default behaviour returns \c -1 for all attributes.
280 	 */
281 	virtual int32_t get_training_attribute(TrainingAttribute attr) const;
282 
283 	void remove(EditorGameBase&);
284 	virtual void destroy(EditorGameBase&);
285 
286 	//  The next functions are really only needed in games, not in the editor.
287 	void schedule_destroy(Game&);
288 	uint32_t schedule_act(Game&, uint32_t tdelta, uint32_t data = 0);
289 	virtual void act(Game&, uint32_t data);
290 
get_logsink()291 	LogSink* get_logsink() {
292 		return logsink_;
293 	}
294 	void set_logsink(LogSink*);
295 
296 	/// Called when a new logsink is set. Used to give general information.
297 	virtual void log_general_info(const EditorGameBase&) const;
298 
get_owner()299 	Player* get_owner() const {
300 		return owner_;
301 	}
302 
owner()303 	const Player& owner() const {
304 		assert(get_owner());
305 		return *owner_;
306 	}
307 
308 	// Header bytes to distinguish between data packages for the different
309 	// MapObject classes. Be careful in changing those, since they are written
310 	// to files.
311 	enum {
312 		HeaderMapObject = 1,
313 		HeaderImmovable = 2,
314 		// 3 was battle object.
315 		// 4 was attack controller.
316 		HeaderBattle = 5,
317 		HeaderCritter = 6,
318 		HeaderWorker = 7,
319 		HeaderWareInstance = 8,
320 		HeaderShip = 9,
321 		HeaderPortDock = 10,
322 		HeaderShipFleet = 11,
323 		HeaderFerryFleet = 12,
324 	};
325 
326 	/**
327 	 * Returns whether this immovable was reserved by a worker.
328 	 */
329 	bool is_reserved_by_worker() const;
330 
331 	/**
332 	 * Change whether this immovable is marked as reserved by a worker.
333 	 */
334 	void set_reserved_by_worker(bool reserve);
335 
336 	/**
337 	 * Static load functions of derived classes will return a pointer to
338 	 * a Loader class. The caller needs to call the virtual functions
339 	 * \ref load for all instances loaded that way, after that call
340 	 * \ref load_pointers for all instances loaded that way and finally
341 	 * call \ref load_finish for all instances loaded that way.
342 	 * Those are the three phases of loading. After the last phase,
343 	 * all Loader objects should be deleted.
344 	 */
345 	struct Loader {
346 		EditorGameBase* egbase_;
347 		MapObjectLoader* mol_;
348 		MapObject* object_;
349 
350 	protected:
LoaderLoader351 		Loader() : egbase_(nullptr), mol_(nullptr), object_(nullptr) {
352 		}
353 
354 	public:
~LoaderLoader355 		virtual ~Loader() {
356 		}
357 
initLoader358 		void init(EditorGameBase& e, MapObjectLoader& m, MapObject& object) {
359 			egbase_ = &e;
360 			mol_ = &m;
361 			object_ = &object;
362 		}
363 
egbaseLoader364 		EditorGameBase& egbase() {
365 			return *egbase_;
366 		}
molLoader367 		MapObjectLoader& mol() {
368 			return *mol_;
369 		}
get_objectLoader370 		MapObject* get_object() {
371 			return object_;
372 		}
getLoader373 		template <typename T> T& get() {
374 			return dynamic_cast<T&>(*object_);
375 		}
376 
377 	protected:
378 		void load(FileRead&);
379 
380 	public:
381 		virtual void load_pointers();
382 		virtual void load_finish();
383 	};
384 
385 	/// This is just a fail-safe guard for the time until we fully transition
386 	/// to the new MapObject saving system
has_new_save_support()387 	virtual bool has_new_save_support() {
388 		return false;
389 	}
390 
391 	virtual void save(EditorGameBase&, MapObjectSaver&, FileWrite&);
392 	// Pure MapObjects cannot be loaded
393 
394 protected:
395 	/// Called only when the oject is logically created in the simulation. If
396 	/// called again, such as when the object is loaded from a savegame, it will
397 	/// cause bugs.
398 	virtual bool init(EditorGameBase&);
399 
400 	virtual void cleanup(EditorGameBase&);
401 
402 	/// Draws census and statistics on screen
403 	void do_draw_info(const InfoToDraw& info_to_draw,
404 	                  const std::string& census,
405 	                  const std::string& statictics,
406 	                  const Vector2f& field_on_dst,
407 	                  const float scale,
408 	                  RenderTarget* dst) const;
409 
410 #ifdef _WIN32
411 	void molog(char const* fmt, ...) const __attribute__((format(gnu_printf, 2, 3)));
412 #else
413 	void molog(char const* fmt, ...) const __attribute__((format(__printf__, 2, 3)));
414 #endif
415 
416 	const MapObjectDescr* descr_;
417 	Serial serial_;
418 	LogSink* logsink_;
419 	Player* owner_;
420 
421 	/**
422 	 * MapObjects like trees are reserved by a worker that is walking
423 	 * towards them, so that e.g. two lumberjacks don't attempt to
424 	 * work on the same tree simultaneously or two hunters try to hunt
425 	 * the same animal.
426 	 */
427 	bool reserved_by_worker_;
428 
429 private:
430 	DISALLOW_COPY_AND_ASSIGN(MapObject);
431 };
432 
get_reverse_dir(int32_t const dir)433 inline int32_t get_reverse_dir(int32_t const dir) {
434 	return 1 + ((dir - 1) + 3) % 6;
435 }
436 
437 /**
438  *
439  * Keeps the list of all objects currently in the game.
440  */
441 struct ObjectManager {
442 	using MapObjectMap = std::unordered_map<Serial, MapObject*>;
443 
ObjectManagerObjectManager444 	ObjectManager() {
445 		lastserial_ = 0;
446 	}
447 	~ObjectManager();
448 
449 	void cleanup(EditorGameBase&);
450 
get_objectObjectManager451 	MapObject* get_object(Serial const serial) const {
452 		const MapObjectMap::const_iterator it = objects_.find(serial);
453 		return it != objects_.end() ? it->second : nullptr;
454 	}
455 
456 	void insert(MapObject*);
457 	void remove(MapObject&);
458 
object_still_availableObjectManager459 	bool object_still_available(const MapObject* const t) const {
460 		if (!t)
461 			return false;
462 		MapObjectMap::const_iterator it = objects_.begin();
463 		while (it != objects_.end()) {
464 			if (it->second == t)
465 				return true;
466 			++it;
467 		}
468 		return false;
469 	}
470 
471 	/**
472 	 * When saving the map object, ordere matters. Return a vector of all ids
473 	 * that are currently available;
474 	 */
475 	std::vector<Serial> all_object_serials_ordered() const;
476 
477 private:
478 	Serial lastserial_;
479 	MapObjectMap objects_;
480 
481 	DISALLOW_COPY_AND_ASSIGN(ObjectManager);
482 };
483 
484 /**
485  * Provides a safe pointer to a MapObject
486  */
487 struct ObjectPointer {
488 	// Provide default constructor to shut up cppcheck.
ObjectPointerObjectPointer489 	ObjectPointer() {
490 		serial_ = 0;
491 	}
ObjectPointerObjectPointer492 	ObjectPointer(const MapObject* const obj) {
493 		serial_ = obj ? obj->serial_ : 0;
494 	}
495 	// can use standard copy constructor and assignment operator
496 
497 	ObjectPointer& operator=(const MapObject* const obj) {
498 		serial_ = obj ? obj->serial_ : 0;
499 		return *this;
500 	}
501 
is_setObjectPointer502 	bool is_set() const {
503 		return serial_;
504 	}
505 
506 	// TODO(unknown): dammit... without an EditorGameBase object, we can't implement a
507 	// MapObject* operator (would be really nice)
508 	MapObject* get(const EditorGameBase&);
509 	MapObject* get(const EditorGameBase& egbase) const;
510 
511 	bool operator<(const ObjectPointer& other) const {
512 		return serial_ < other.serial_;
513 	}
514 	bool operator==(const ObjectPointer& other) const {
515 		return serial_ == other.serial_;
516 	}
517 	bool operator!=(const ObjectPointer& other) const {
518 		return serial_ != other.serial_;
519 	}
520 
serialObjectPointer521 	uint32_t serial() const {
522 		return serial_;
523 	}
524 
525 private:
526 	uint32_t serial_;
527 };
528 
529 template <class T> struct OPtr {
mOPtr530 	OPtr(T* const obj = nullptr) : m(obj) {
531 	}
532 
533 	OPtr& operator=(T* const obj) {
534 		m = obj;
535 		return *this;
536 	}
537 
is_setOPtr538 	bool is_set() const {
539 		return m.is_set();
540 	}
541 
getOPtr542 	T* get(const EditorGameBase& egbase) {
543 		return static_cast<T*>(m.get(egbase));
544 	}
getOPtr545 	T* get(const EditorGameBase& egbase) const {
546 		return static_cast<T*>(m.get(egbase));
547 	}
548 
549 	bool operator<(const OPtr<T>& other) const {
550 		return m < other.m;
551 	}
552 	bool operator==(const OPtr<T>& other) const {
553 		return m == other.m;
554 	}
555 	bool operator!=(const OPtr<T>& other) const {
556 		return m != other.m;
557 	}
558 
serialOPtr559 	Serial serial() const {
560 		return m.serial();
561 	}
562 
563 private:
564 	ObjectPointer m;
565 };
566 
567 struct CmdDestroyMapObject : public GameLogicCommand {
CmdDestroyMapObjectCmdDestroyMapObject568 	CmdDestroyMapObject() : GameLogicCommand(0), obj_serial(0) {
569 	}  ///< For savegame loading
570 	CmdDestroyMapObject(uint32_t t, MapObject&);
571 	void execute(Game&) override;
572 
573 	void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
574 	void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
575 
idCmdDestroyMapObject576 	QueueCommandTypes id() const override {
577 		return QueueCommandTypes::kDestroyMapObject;
578 	}
579 
580 private:
581 	Serial obj_serial;
582 };
583 
584 struct CmdAct : public GameLogicCommand {
CmdActCmdAct585 	CmdAct() : GameLogicCommand(0), obj_serial(0), arg(0) {
586 	}  ///< For savegame loading
587 	CmdAct(uint32_t t, MapObject&, int32_t a);
588 
589 	void execute(Game&) override;
590 
591 	void write(FileWrite&, EditorGameBase&, MapObjectSaver&) override;
592 	void read(FileRead&, EditorGameBase&, MapObjectLoader&) override;
593 
idCmdAct594 	QueueCommandTypes id() const override {
595 		return QueueCommandTypes::kAct;
596 	}
597 
598 private:
599 	Serial obj_serial;
600 	int32_t arg;
601 };
602 }  // namespace Widelands
603 
604 #endif  // end of include guard: WL_LOGIC_MAP_OBJECTS_MAP_OBJECT_H
605