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 /// '<basename>_(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