1 /*
2  *  The ManaPlus Client
3  *  Copyright (C) 2004-2009  The Mana World Development Team
4  *  Copyright (C) 2009-2010  The Mana Developers
5  *  Copyright (C) 2011-2019  The ManaPlus Developers
6  *  Copyright (C) 2019-2021  Andrei Karas
7  *
8  *  This file is part of The ManaPlus Client.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef RESOURCES_MAP_MAP_H
25 #define RESOURCES_MAP_MAP_H
26 
27 #include "position.h"
28 
29 #include "being/actor.h"
30 
31 #include "enums/render/rendertype.h"
32 
33 #include "enums/resources/map/blocktype.h"
34 #include "enums/resources/map/maplayerposition.h"
35 #include "enums/resources/map/maptype.h"
36 
37 #include "listeners/configlistener.h"
38 
39 #include "utils/vector.h"
40 
41 #include "resources/memorycounter.h"
42 
43 #include "resources/map/properties.h"
44 
45 class AmbientLayer;
46 #ifdef USE_OPENGL
47 class AtlasResource;
48 #endif  // USE_OPENGL
49 
50 class MapHeights;
51 class MapItem;
52 class MapLayer;
53 class ObjectsLayer;
54 class SpecialLayer;
55 class Tileset;
56 class TileAnimation;
57 class WalkLayer;
58 
59 struct MetaTile;
60 
61 typedef STD_VECTOR<Tileset*> Tilesets;
62 typedef STD_VECTOR<MapLayer*> Layers;
63 typedef Layers::const_iterator LayersCIter;
64 
65 typedef STD_VECTOR<AmbientLayer*> AmbientLayerVector;
66 typedef AmbientLayerVector::const_iterator AmbientLayerVectorCIter;
67 typedef AmbientLayerVector::iterator AmbientLayerVectorIter;
68 
69 /**
70  * A tile map.
71  */
72 class Map final : public Properties,
73                   public ConfigListener,
74                   public MemoryCounter
75 {
76     public:
77         /**
78          * Constructor, taking map and tile size as parameters.
79          */
80         Map(const std::string &name,
81             const int width,
82             const int height,
83             const int tileWidth,
84             const int tileHeight);
85 
86         A_DELETE_COPY(Map)
87 
88         /**
89          * Destructor.
90          */
91         ~Map() override final;
92 
93         /**
94          * Initialize ambient layers. Has to be called after all the properties
95          * are set.
96          */
97         void initializeAmbientLayers() restrict2;
98 
99         /**
100          * Updates animations. Called as needed.
101          */
102         void update(const int ticks) restrict2;
103 
104         /**
105          * Draws the map to the given graphics output. This method draws all
106          * layers, actors and overlay effects.
107          */
108         void draw(Graphics *restrict const graphics,
109                   int scrollX,
110                   int scrollY) restrict2 A_NONNULL(2);
111 
112         /**
113          * Visualizes collision layer for debugging
114          */
115         void drawCollision(Graphics *restrict const graphics,
116                            const int scrollX,
117                            const int scrollY,
118                            const MapTypeT drawFlags) const
119                            restrict2 A_NONNULL(2);
120 
121         /**
122          * Adds a layer to this map. The map takes ownership of the layer.
123          */
124         void addLayer(MapLayer *const layer) restrict2 A_NONNULL(2);
125 
126         /**
127          * Adds a tileset to this map. The map takes ownership of the tileset.
128          */
129         void addTileset(Tileset *const tileset) restrict2 A_NONNULL(2);
130 
131         /**
132          * Finds the tile set that a tile with the given global id is part of.
133          */
134         const Tileset *getTilesetWithGid(const int gid) const
135                                          restrict2 A_WARN_UNUSED;
136 
137         /**
138          * Get tile reference.
139          */
140         const MetaTile *getMetaTile(const int x,
141                                     const int y) const
142                                     restrict2 A_WARN_UNUSED;
143 
144         void addBlockMask(const int x, const int y,
145                           const BlockTypeT type) restrict2;
146 
147         void setBlockMask(const int x, const int y,
148                           const BlockTypeT type) restrict2;
149 
150         /**
151          * Gets walkability for a tile with a blocking bitmask. When called
152          * without walkmask, only blocks against colliding tiles.
153          */
154         bool getWalk(const int x, const int y,
155                      const unsigned char blockWalkMask) const
156                      restrict2 A_WARN_UNUSED;
157 
158         void setWalk(const int x, const int y) restrict2;
159 
160         unsigned char getBlockMask(const int x,
161                                    const int y) const restrict2;
162 
163         /**
164          * Returns the width of this map in tiles.
165          */
getWidth()166         int getWidth() const restrict2 noexcept2 A_WARN_UNUSED
167         { return mWidth; }
168 
169         /**
170          * Returns the height of this map in tiles.
171          */
getHeight()172         int getHeight() const restrict2 noexcept2 A_WARN_UNUSED
173         { return mHeight; }
174 
175         /**
176          * Returns the tile width of this map.
177          */
getTileWidth()178         int getTileWidth() const restrict2 noexcept2 A_WARN_UNUSED
179         { return mTileWidth; }
180 
181         /**
182          * Returns the tile height used by this map.
183          */
getTileHeight()184         int getTileHeight() const restrict2 noexcept2 A_WARN_UNUSED
185         { return mTileHeight; }
186 
187         const std::string getMusicFile() const restrict2 A_WARN_UNUSED;
188 
189         void setMusicFile(const std::string &restrict file) restrict2;
190 
191         const std::string getName() const restrict2 A_WARN_UNUSED;
192 
193         /**
194          * Gives the map id based on filepath (ex: 009-1)
195          */
196         const std::string getFilename() const restrict2 A_WARN_UNUSED;
197 
198         const std::string getGatName() const restrict2 A_WARN_UNUSED;
199 
200         /**
201          * Find a path from one location to the next.
202          */
203         Path findPath(const int startX, const int startY,
204                       const int destX, const int destY,
205                       const unsigned char blockWalkmask,
206                       const int maxCost) restrict2 A_WARN_UNUSED;
207 
208         /**
209          * Adds a particle effect
210          */
211         void addParticleEffect(const std::string &restrict effectFile,
212                                const int x,
213                                const int y,
214                                const int w,
215                                const int h) restrict2;
216 
217         /**
218          * Initializes all added particle effects
219          */
220         void initializeParticleEffects() const restrict2;
221 
222         /**
223          * Adds a tile animation to the map
224          */
225         void addAnimation(const int gid,
226                           TileAnimation *restrict const animation) restrict2
227                           A_NONNULL(3);
228 
229         void setDrawLayersFlags(const MapTypeT &restrict n) restrict2;
230 
getDrawLayersFlags()231         MapTypeT getDrawLayersFlags() const restrict2 A_WARN_UNUSED
232         { return mDrawLayersFlags; }
233 
234         void addExtraLayer() restrict2;
235 
236         void saveExtraLayer() const restrict2;
237 
getTempLayer()238         SpecialLayer *getTempLayer() const restrict2 noexcept2 A_WARN_UNUSED
239         { return mTempLayer; }
240 
getSpecialLayer()241         SpecialLayer *getSpecialLayer() const restrict2 noexcept2 A_WARN_UNUSED
242         { return mSpecialLayer; }
243 
setHasWarps(const bool n)244         void setHasWarps(const bool n) restrict2 noexcept2
245         { mHasWarps = n; }
246 
getHasWarps()247         bool getHasWarps() const restrict2 noexcept2 A_WARN_UNUSED
248         { return mHasWarps; }
249 
250         std::string getUserMapDirectory() const restrict2 A_WARN_UNUSED;
251 
252         void addPortal(const std::string &restrict name,
253                        const int type,
254                        const int x, const int y,
255                        const int dx, const int dy) restrict2;
256 
257         void addRange(const std::string &restrict name,
258                       const int type,
259                       const int x, const int y,
260                       const int dx, const int dy) restrict2;
261 
262         void addPortalTile(const std::string &restrict name,
263                            const int type,
264                            const int x, const int y) restrict2;
265 
266         void updatePortalTile(const std::string &restrict name,
267                               const int type,
268                               const int x, const int y,
269                               const bool addNew) restrict2;
270 
getPortals()271         const STD_VECTOR<MapItem*> &getPortals() const restrict2 noexcept2
272                                                 A_WARN_UNUSED
273         { return mMapPortals; }
274 
275         /**
276          * Gets the tile animation for a specific gid
277          */
278         const TileAnimation *getAnimationForGid(const int gid)
279                                                 const restrict2 A_WARN_UNUSED;
280 
281         void optionChanged(const std::string &restrict value)
282                            restrict2 override final;
283 
284         MapItem *findPortalXY(const int x,
285                               const int y) const restrict2 A_WARN_UNUSED;
286 
getActorsCount()287         int getActorsCount() const restrict2 A_WARN_UNUSED
288         { return CAST_S32(mActors.size()); }
289 
290         void setPvpMode(const int mode) restrict2;
291 
getPvpMode()292         int getPvpMode() const restrict2 noexcept2 A_WARN_UNUSED
293         { return mPvp; }
294 
getObjectsLayer()295         const ObjectsLayer* getObjectsLayer() const restrict2 noexcept2
296                                             A_WARN_UNUSED
297         { return mObjects; }
298 
299         std::string getObjectData(const unsigned x,
300                                   const unsigned y,
301                                   const int type) const
302                                   restrict2 A_WARN_UNUSED;
303 
304         void indexTilesets() restrict2;
305 
306         void clearIndexedTilesets() restrict2;
307 
308         void setActorsFix(const int x, const int y) restrict2;
309 
getVersion()310         int getVersion() const restrict2 noexcept2 A_WARN_UNUSED
311         { return mVersion; }
312 
setVersion(const int n)313         void setVersion(const int n) restrict2 noexcept2
314         { mVersion = n; }
315 
316         void reduce() restrict2;
317 
redrawMap()318         void redrawMap() restrict2 noexcept2
319         { mRedrawMap = true; }
320 
empty()321         bool empty() const restrict2 A_WARN_UNUSED
322         { return mLayers.empty(); }
323 
setCustom(const bool b)324         void setCustom(const bool b) restrict2 noexcept2
325         { mCustom = b; }
326 
isCustom()327         bool isCustom() const restrict2 noexcept2 A_WARN_UNUSED
328         { return mCustom; }
329 
getTileAnimations()330         const std::map<int, TileAnimation*> &getTileAnimations() const
331                                             restrict2 noexcept2 A_WARN_UNUSED
332         { return mTileAnimations; }
333 
334 #ifdef USE_OPENGL
335         int getAtlasCount() const restrict2 A_WARN_UNUSED;
336 
setAtlas(AtlasResource * restrict const atlas)337         void setAtlas(AtlasResource *restrict const atlas) restrict2 noexcept2
338         { mAtlas = atlas; }
339 
haveAtlas()340         bool haveAtlas() const
341         { return mAtlas != nullptr; }
342 #endif  // USE_OPENGL
343 
getMetaTiles()344         const MetaTile *getMetaTiles() const restrict2 noexcept2
345         { return mMetaTiles; }
346 
getWalkLayer()347         const WalkLayer *getWalkLayer() const restrict2 noexcept2
348         { return mWalkLayer; }
349 
setWalkLayer(WalkLayer * restrict const layer)350         void setWalkLayer(WalkLayer *restrict const layer) restrict2 noexcept2
351         { mWalkLayer = layer; }
352 
353         void addHeights(const MapHeights *restrict const heights) restrict2
354                         A_NONNULL(2);
355 
356         uint8_t getHeightOffset(const int x, const int y) const restrict2;
357 
358         void setMask(const int mask) restrict2;
359 
360         void updateDrawLayersList() restrict2;
361 
isHeightsPresent()362         bool isHeightsPresent() const restrict2 noexcept2
363         { return mHeights != nullptr; }
364 
365         void updateConditionLayers() restrict2;
366 
367         void preCacheLayers() restrict2;
368 
369         int calcMemoryLocal() const override final;
370 
371         int calcMemoryChilds(const int level) const override final;
372 
getCounterName()373         std::string getCounterName() const override final
374         { return mName; }
375 
376         void screenResized();
377 
378     protected:
379         friend class Actor;
380         friend class Minimap;
381 
382         /**
383          * Adds an actor to the map.
384          */
385         Actors::iterator addActor(Actor *const actor) restrict2 A_NONNULL(2);
386 
387         /**
388          * Removes an actor from the map.
389          */
390         void removeActor(const Actors::iterator &restrict iterator) restrict2;
391 
392     private:
393         /**
394          * Updates scrolling of ambient layers. Has to be called each game tick.
395          */
396         void updateAmbientLayers(const float scrollX,
397                                  const float scrollY) restrict2;
398 
399         /**
400          * Draws the foreground or background layers to the given graphics output.
401          */
402         void drawAmbientLayers(Graphics *restrict const graphics,
403                                const MapLayerPositionT type,
404                                const int detail) const restrict2 A_NONNULL(2);
405 
406         /**
407          * Tells whether the given coordinates fall within the map boundaries.
408          */
409         bool contains(const int x,
410                       const int y) const restrict2 A_WARN_UNUSED;
411 
412         const int mWidth;
413         const int mHeight;
414         const int mTileWidth;
415         const int mTileHeight;
416         int mMaxTileHeight;
417         MetaTile *const mMetaTiles;
418         WalkLayer *mWalkLayer;
419         Layers mLayers;
420         Layers mDrawUnderLayers;
421         Layers mDrawOverLayers;
422         Tilesets mTilesets;
423         Actors mActors;
424         bool mHasWarps;
425 
426         // draw flags
427         MapTypeT mDrawLayersFlags;
428 
429         // Pathfinding members
430         unsigned int mOnClosedList;
431         unsigned int mOnOpenList;
432 
433         // Overlay data
434         AmbientLayerVector mBackgrounds;
435         AmbientLayerVector mForegrounds;
436         float mLastAScrollX;
437         float mLastAScrollY;
438 
439         // Particle effect data
440         struct ParticleEffectData final
441         {
ParticleEffectDatafinal442             ParticleEffectData(const std::string &restrict file0,
443                                const int x0,
444                                const int y0,
445                                const int w0,
446                                const int h0) noexcept2 :
447                 file(file0),
448                 x(x0),
449                 y(y0),
450                 w(w0),
451                 h(h0)
452             {
453             }
454 
455             A_DEFAULT_COPY(ParticleEffectData)
456 
457             const2 std::string file;
458             const2 int x;
459             const2 int y;
460             const2 int w;
461             const2 int h;
462         };
463         STD_VECTOR<ParticleEffectData> mParticleEffects;
464 
465         STD_VECTOR<MapItem*> mMapPortals;
466 
467         std::map<int, TileAnimation*> mTileAnimations;
468 
469         std::string mName;
470         int mOverlayDetail;
471         float mOpacity;
472         const RenderType mOpenGL;
473         int mPvp;
474         bool mTilesetsIndexed;
475         Tileset** mIndexedTilesets;
476         int mIndexedTilesetsSize;
477         int mActorFixX;
478         int mActorFixY;
479         int mVersion;
480 
481         SpecialLayer *mSpecialLayer;
482         SpecialLayer *mTempLayer;
483         ObjectsLayer *mObjects;
484         MapLayer *mFringeLayer;
485 
486         int mLastX;
487         int mLastY;
488         int mLastScrollX;
489         int mLastScrollY;
490 
491         int mDrawX;
492         int mDrawY;
493         int mDrawScrollX;
494         int mDrawScrollY;
495         int mMask;
496 #ifdef USE_OPENGL
497         AtlasResource *mAtlas;
498 #endif  // USE_OPENGL
499 
500         const MapHeights *mHeights;
501         bool mRedrawMap;
502         bool mBeingOpacity;
503         bool mCachedDraw;
504         bool mCustom;
505         bool mDrawOnlyFringe;
506         bool mClear;
507 };
508 
509 #endif  // RESOURCES_MAP_MAP_H
510