ManaPlus
mapreader.cpp
Go to the documentation of this file.
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  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "resources/mapreader.h"
24 
25 #include "configuration.h"
26 #ifdef USE_OPENGL
27 #include "graphicsmanager.h"
28 #endif // USE_OPENGL
29 #include "main.h"
30 
32 
35 
36 #include "fs/virtfs/fs.h"
37 
38 #include "resources/map/map.h"
40 #include "resources/map/maplayer.h"
41 #include "resources/map/tileset.h"
42 
43 #include "resources/beingcommon.h"
45 
46 #include "resources/image/image.h"
47 
48 #ifdef USE_OPENGL
49 #include "resources/db/mapdb.h"
52 #endif // USE_OPENGL
53 
55 
57 
59 
60 #include "utils/base64.h"
61 #include "utils/checkutils.h"
62 #include "utils/delete2.h"
63 #include "utils/stringmap.h"
64 
66 
67 #include <zlib.h>
68 
69 #include "debug.h"
70 
71 typedef std::map<std::string, XmlNodePtr>::iterator LayerInfoIterator;
72 typedef std::set<XML::Document*>::iterator DocIterator;
73 
74 #ifdef USE_OPENGL
76 #endif // USE_OPENGL
77 
78 namespace
79 {
80  std::map<std::string, XmlNodePtr> mKnownLayers;
81  std::set<XML::Document*> mKnownDocs;
82 } // namespace
83 
84 static int inflateMemory(unsigned char *restrict const in,
85  const unsigned int inLength,
86  unsigned char *&restrict out,
87  unsigned int &restrict outLength);
88 
89 static int inflateMemory(unsigned char *restrict const in,
90  const unsigned int inLength,
91  unsigned char *&restrict out);
92 
93 static std::string resolveRelativePath(std::string base, std::string relative)
94 {
95  // Remove trailing "/", if present
96  size_t i = base.length();
97  if (base.at(i - 1) == '/')
98  base.erase(i - 1, i);
99 
100  while (relative.substr(0, 3) == "../")
101  {
102  relative.erase(0, 3); // Remove "../"
103  if (!base.empty()) // If base is already empty, we can't trim anymore
104  {
105  i = base.find_last_of('/');
106  if (i == std::string::npos)
107  i = 0;
108  base.erase(i, base.length()); // Remove deepest folder in base
109  }
110  }
111 
112  // Re-add trailing slash, if needed
113  if (!base.empty() && base[base.length() - 1] != '/')
114  base.append("/");
115 
116  return base + relative;
117 }
118 
123 int inflateMemory(unsigned char *restrict const in,
124  const unsigned int inLength,
125  unsigned char *&restrict out,
126  unsigned int &restrict outLength)
127 {
128  int bufferSize = 256 * 1024;
129  out = static_cast<unsigned char*>(calloc(bufferSize, 1));
130 
131  z_stream strm;
132  strm.zalloc = nullptr;
133  strm.zfree = nullptr;
134  strm.opaque = nullptr;
135  strm.next_in = in;
136  strm.avail_in = inLength;
137  strm.next_out = out;
138  strm.avail_out = bufferSize;
139 
140 PRAGMACLANG6GCC(GCC diagnostic push)
141 PRAGMACLANG6GCC(GCC diagnostic ignored "-Wold-style-cast")
142  int ret = inflateInit2(&strm, 15 + 32);
143 PRAGMACLANG6GCC(GCC diagnostic pop)
144 
145  if (ret != Z_OK)
146  return ret;
147 
148  do
149  {
150  if (strm.next_out == nullptr)
151  {
152  inflateEnd(&strm);
153  return Z_MEM_ERROR;
154  }
155 
156  ret = inflate(&strm, Z_NO_FLUSH);
157  if (ret == Z_STREAM_ERROR)
158  return ret;
159 
160  switch (ret)
161  {
162  case Z_NEED_DICT:
163  ret = Z_DATA_ERROR;
165  case Z_DATA_ERROR:
166  case Z_MEM_ERROR:
167  (void) inflateEnd(&strm);
168  return ret;
169  default:
170  break;
171  }
172 
173  if (ret != Z_STREAM_END)
174  {
175  out = static_cast<unsigned char*>(realloc(out, bufferSize * 2));
176 
177  if (out == nullptr)
178  {
179  inflateEnd(&strm);
180  return Z_MEM_ERROR;
181  }
182 
183  strm.next_out = out + CAST_SIZE(bufferSize);
184  strm.avail_out = bufferSize;
185  bufferSize *= 2;
186  }
187  }
188  while (ret != Z_STREAM_END);
189 
190  outLength = bufferSize - strm.avail_out;
191  (void) inflateEnd(&strm);
192  return Z_OK;
193 }
194 
195 int inflateMemory(unsigned char *restrict const in,
196  const unsigned int inLength,
197  unsigned char *&restrict out)
198 {
199  unsigned int outLength = 0;
200  const int ret = inflateMemory(in, inLength, out, outLength);
201 
202  if (ret != Z_OK || (out == nullptr))
203  {
204  if (ret == Z_MEM_ERROR)
205  {
206  reportAlways("Error: Out of memory while decompressing map data!")
207  }
208  else if (ret == Z_VERSION_ERROR)
209  {
210  reportAlways("Error: Incompatible zlib version!")
211  }
212  else if (ret == Z_DATA_ERROR)
213  {
214  reportAlways("Error: Incorrect zlib compressed data!")
215  }
216  else
217  {
218  reportAlways("Error: Unknown error while decompressing map data!")
219  }
220 
221  free(out);
222  out = nullptr;
223  outLength = 0;
224  }
225 
226  return outLength;
227 }
228 
229 void MapReader::addLayerToList(const std::string &fileName,
230  const SkipError skipError)
231 {
234  skipError);
235  XmlNodePtrConst node = doc->rootNode();
236  if (node == nullptr)
237  {
238  delete doc;
239  return;
240  }
241 
242  int cnt = 0;
243  for_each_xml_child_node(childNode, node)
244  {
245  if (!xmlNameEqual(childNode, "layer"))
246  continue;
247  std::string name = XML::getProperty(childNode, "name", "");
248  if (name.empty())
249  continue;
250  name = toLower(name);
251  logger->log("found patch layer: " + name);
252  mKnownLayers[name] = childNode;
253  mKnownDocs.insert(doc);
254  cnt ++;
255  }
256  if (cnt == 0)
257  delete doc;
258 }
259 
260 Map *MapReader::readMap(const std::string &restrict filename,
261  const std::string &restrict realFilename)
262 {
263  BLOCK_START("MapReader::readMap str")
264  logger->log("Attempting to read map %s", realFilename.c_str());
265 
266  XML::Document doc(realFilename, UseVirtFs_true, SkipError_false);
267  if (!doc.isLoaded())
268  {
269  BLOCK_END("MapReader::readMap str")
270  return createEmptyMap(filename, realFilename);
271  }
272 
273  XmlNodePtrConst node = doc.rootNode();
274 
275  Map *map = nullptr;
276  // Parse the inflated map data
277  if (node != nullptr)
278  {
279  if (!xmlNameEqual(node, "map"))
280  logger->log("Error: Not a map file (%s)!", realFilename.c_str());
281  else
282  map = readMap(node, realFilename);
283  }
284  else
285  {
286  reportAlways("Error while parsing map file (%s)!",
287  realFilename.c_str())
288  }
289 
290  if (map != nullptr)
291  {
292  map->setProperty("_filename", realFilename);
293  map->setProperty("_realfilename", filename);
294 
295  if (map->getProperty("music", std::string()).empty())
296  updateMusic(map);
297 
298  map->updateConditionLayers();
299  map->preCacheLayers();
300  }
301 
302  BLOCK_END("MapReader::readMap str")
303  return map;
304 }
305 
306 void MapReader::loadLayers(const std::string &path)
307 {
308  BLOCK_START("MapReader::loadLayers")
310  BLOCK_END("MapReader::loadLayers")
311 }
312 
314 {
316  delete (*it);
317  mKnownLayers.clear();
318  mKnownDocs.clear();
319 }
320 
321 static void loadReplaceLayer(const LayerInfoIterator &it,
322  Map *const map) A_NONNULL(2);
323 static void loadReplaceLayer(const LayerInfoIterator &it,
324  Map *const map)
325 {
326  MapReader::readLayer((*it).second, map);
327 }
328 
329 Map *MapReader::readMap(XmlNodePtrConst node, const std::string &path)
330 {
331  if (node == nullptr)
332  return nullptr;
333 
334  BLOCK_START("MapReader::readMap xml")
335  // Take the filename off the path
336  const std::string pathDir = path.substr(0, path.rfind('/') + 1);
337 
338  const int w = XML::getProperty(node, "width", 0);
339  const int h = XML::getProperty(node, "height", 0);
340  const int tilew = XML::getProperty(node, "tilewidth", -1);
341  const int tileh = XML::getProperty(node, "tileheight", -1);
342 
343  const bool showWarps = config.getBoolValue("warpParticle");
344  const std::string warpPath = pathJoin(paths.getStringValue("particles"),
345  paths.getStringValue("portalEffectFile"));
346 
347  if (tilew < 0 || tileh < 0)
348  {
349  reportAlways("MapReader: Warning: "
350  "Uninitialized tile width or height value for map: %s",
351  path.c_str())
352  BLOCK_END("MapReader::readMap xml")
353  return nullptr;
354  }
355 
356  logger->log("loading replace layer list");
357  loadLayers(path + "_replace.d");
358 
359  Map *const map = new Map(path,
360  w, h,
361  tilew, tileh);
362 
363  map->screenResized();
364 
365  const std::string fileName = path.substr(path.rfind(dirSeparator) + 1);
366  map->setProperty("shortName", fileName);
367 
368 #ifdef USE_OPENGL
369  BLOCK_START("MapReader::readMap load atlas")
370  if (graphicsManager.getUseAtlases())
371  {
372  const MapInfo *const info = MapDB::getMapAtlas(fileName);
373  if (info != nullptr)
374  {
375  map->setAtlas(Loader::getAtlas(
376  info->atlas,
377  *info->files));
378  }
379  else
380  {
381  reportAlways("Missing atlas for map: %s",
382  fileName.c_str())
383  }
384  }
385  BLOCK_END("MapReader::readMap load atlas")
386 #endif // USE_OPENGL
387 
388  for_each_xml_child_node(childNode, node)
389  {
390  if (xmlNameEqual(childNode, "tileset"))
391  {
392  Tileset *const tileset = readTileset(childNode, pathDir, map);
393  if (tileset != nullptr)
394  map->addTileset(tileset);
395  }
396  else if (xmlNameEqual(childNode, "layer"))
397  {
398  std::string name = XML::getProperty(childNode, "name", "");
399  name = toLower(name);
400  LayerInfoIterator it = mKnownLayers.find(name);
401  if (it == mKnownLayers.end())
402  {
403  readLayer(childNode, map);
404  }
405  else
406  {
407  logger->log("load replace layer: " + name);
408  loadReplaceLayer(it, map);
409  }
410  }
411  else if (xmlNameEqual(childNode, "properties"))
412  {
413  readProperties(childNode, map);
414  map->setVersion(atoi(map->getProperty(
415  "manaplus version", std::string()).c_str()));
416  }
417  else if (xmlNameEqual(childNode, "objectgroup"))
418  {
419  // The object group offset is applied to each object individually
420  const int tileOffsetX = XML::getProperty(childNode, "x", 0);
421  const int tileOffsetY = XML::getProperty(childNode, "y", 0);
422  const int offsetX = tileOffsetX * tilew;
423  const int offsetY = tileOffsetY * tileh;
424  const bool showParticles =
425  config.getBoolValue("mapparticleeffects");
426 
427  for_each_xml_child_node(objectNode, childNode)
428  {
429  if (xmlNameEqual(objectNode, "object"))
430  {
431  std::string objType = XML::getProperty(
432  objectNode, "type", "");
433 
434  objType = toUpper(objType);
435 
436 /*
437  if (objType == "NPC" ||
438  objType == "SCRIPT")
439  {
440  logger->log("hidden obj: " + objType);
441  // Silently skip server-side objects.
442  continue;
443  }
444 */
445 
446  const std::string objName = XML::getProperty(
447  objectNode, "name", "");
448  const int objX = XML::getProperty(objectNode, "x", 0);
449  const int objY = XML::getProperty(objectNode, "y", 0);
450  const int objW = XML::getProperty(objectNode, "width", 0);
451  const int objH = XML::getProperty(objectNode, "height", 0);
452 
453  logger->log("- Loading object name: %s type: %s at %d:%d"
454  " (%dx%d)", objName.c_str(), objType.c_str(),
455  objX, objY, objW, objH);
456 
457  if (objType == "PARTICLE_EFFECT")
458  {
459  if (objName.empty())
460  {
461  logger->log1(" Warning: No particle file given");
462  continue;
463  }
464 
465  if (showParticles)
466  {
467  map->addParticleEffect(objName,
468  objX + offsetX,
469  objY + offsetY,
470  objW,
471  objH);
472  }
473  else
474  {
475  logger->log("Ignore particle effect: " + objName);
476  }
477  }
478  else if (objType == "WARP")
479  {
480  if (showWarps)
481  {
482  map->addParticleEffect(warpPath,
483  objX, objY, objW, objH);
484  }
485  map->addPortal(objName, MapItemType::PORTAL,
486  objX, objY, objW, objH);
487  }
488  else if (objType == "SPAWN")
489  {
490  // TRANSLATORS: spawn name
491 // map->addPortal(_("Spawn: ") + objName,
492 // MapItemType::PORTAL,
493 // objX, objY, objW, objH);
494  }
495  else if (objType == "MUSIC")
496  {
497  map->addRange(objName, MapItemType::MUSIC,
498  objX, objY, objW, objH);
499  }
500  else
501  {
502  logger->log1(" Warning: Unknown object type");
503  }
504  }
505  }
506  }
507  }
508 
509  map->initializeAmbientLayers();
510  map->clearIndexedTilesets();
511  map->setActorsFix(0,
512  atoi(map->getProperty("actorsfix", std::string()).c_str()));
513  map->reduce();
514  map->setWalkLayer(Loader::getWalkLayer(fileName, map));
516  map->updateDrawLayersList();
517  BLOCK_END("MapReader::readMap xml")
518  return map;
519 }
520 
521 void MapReader::readProperties(XmlNodeConstPtrConst node,
522  Properties *const props)
523 {
524  BLOCK_START("MapReader::readProperties")
525  if (node == nullptr)
526  {
527  BLOCK_END("MapReader::readProperties")
528  return;
529  }
530 
531  for_each_xml_child_node(childNode, node)
532  {
533  if (!xmlNameEqual(childNode, "property"))
534  continue;
535 
536  // Example: <property name="name" value="value"/>
537  const std::string name = XML::getProperty(childNode, "name", "");
538  const std::string value = XML::getProperty(childNode, "value", "");
539 
540  if (!name.empty() && !value.empty())
541  {
542  if (name == "name")
543  props->setProperty(name, translator->getStr(value));
544  else
545  props->setProperty(name, value);
546  }
547  }
548  BLOCK_END("MapReader::readProperties")
549 }
550 
551 inline static void setTile(Map *const map,
552  MapLayer *const layer,
553  const MapLayerTypeT &layerType,
554  MapHeights *const heights,
555  const int x, const int y,
556  const int gid) A_NONNULL(1);
557 
558 inline static void setTile(Map *const map,
559  MapLayer *const layer,
560  const MapLayerTypeT &layerType,
561  MapHeights *const heights,
562  const int x, const int y,
563  const int gid)
564 {
565  const Tileset * const set = map->getTilesetWithGid(gid);
566  switch (layerType)
567  {
568  case MapLayerType::TILES:
569  {
570  if (layer == nullptr)
571  break;
572  if (set != nullptr &&
573  !set->isEmpty())
574  {
575  Image *const img = set->get(gid - set->getFirstGid());
576  layer->setTile(x, y, img);
577  }
578  else
579  {
580  layer->setTile(x, y, nullptr);
581  }
582  break;
583  }
584 
586  {
587  if (set != nullptr)
588  {
589  if (map->getVersion() >= 1)
590  {
591  const int collisionId = gid - set->getFirstGid();
592  CollisionTypeT type;
593  if (collisionId < 0 ||
594  collisionId >= CAST_S32(CollisionType::COLLISION_MAX))
595  {
597  }
598  else
599  {
600  type = static_cast<CollisionTypeT>(collisionId);
601  }
602  switch (type)
603  {
606  break;
609  break;
611  map->addBlockMask(x, y, BlockType::AIR);
612  break;
615  break;
618  break;
621  break;
624  break;
626  default:
627  break;
628  }
629  }
630  else
631  {
632  if (gid - set->getFirstGid() != 0)
634  }
635  }
636  break;
637  }
638 
640  {
641  if (set == nullptr || heights == nullptr)
642  break;
643  if (map->getVersion() >= 2)
644  {
645  heights->setHeight(x, y, CAST_U8(
646  gid - set->getFirstGid() + 1));
647  }
648  else
649  {
650  Image *const img = set->get(gid - set->getFirstGid());
651  if (layer != nullptr)
652  layer->setTile(x, y, img);
653  }
654  break;
655  }
656 
657  default:
659  break;
660  }
661 }
662 
663 bool MapReader::readBase64Layer(XmlNodeConstPtrConst childNode,
664  Map *const map,
665  MapLayer *const layer,
666  const MapLayerTypeT &layerType,
667  MapHeights *const heights,
668  const std::string &compression,
669  int &restrict x, int &restrict y,
670  const int w, const int h)
671 {
672  if (childNode == nullptr)
673  return false;
674 
675  if (!compression.empty() && compression != "gzip"
676  && compression != "zlib")
677  {
678  reportAlways("Warning: only gzip and zlib layer"
679  " compression supported!")
680  return false;
681  }
682 
683  // Read base64 encoded map file
684  if (!XmlHaveChildContent(childNode))
685  return true;
686 
687  const size_t len = strlen(XmlChildContent(childNode)) + 1;
688  unsigned char *charData = new unsigned char[len + 1];
689  const char *const xmlChars = XmlChildContent(childNode);
690  const char *charStart = reinterpret_cast<const char*>(xmlChars);
691  if (charStart == nullptr)
692  {
693  delete [] charData;
694  return false;
695  }
696 
697  unsigned char *charIndex = charData;
698 
699  while (*charStart != 0)
700  {
701  if (*charStart != ' ' &&
702  *charStart != '\t' &&
703  *charStart != '\n')
704  {
705  *charIndex = *charStart;
706  charIndex++;
707  }
708  charStart++;
709  }
710  *charIndex = '\0';
711 
712  int binLen;
713  unsigned char *binData = php3_base64_decode(charData,
714  CAST_S32(strlen(reinterpret_cast<char*>(
715  charData))), &binLen);
716 
717  delete [] charData;
718 // XmlFree(const_cast<char*>(xmlChars));
719 
720  if (binData != nullptr)
721  {
722  if (compression == "gzip" || compression == "zlib")
723  {
724  // Inflate the gzipped layer data
725  unsigned char *inflated = nullptr;
726  const unsigned int inflatedSize =
727  inflateMemory(binData, binLen, inflated);
728 
729  free(binData);
730  binData = inflated;
731  binLen = inflatedSize;
732 
733  if (inflated == nullptr)
734  {
735  reportAlways("Error: Could not decompress layer!")
736  return false;
737  }
738  }
739 
740  const std::map<int, TileAnimation*> &tileAnimations
741  = map->getTileAnimations();
742 
743  const bool hasAnimations = !tileAnimations.empty();
744  if (hasAnimations)
745  {
746  for (int i = 0; i < binLen - 3; i += 4)
747  {
748  const int gid = binData[i] |
749  binData[i + 1] << 8 |
750  binData[i + 2] << 16 |
751  binData[i + 3] << 24;
752 
753  setTile(map, layer, layerType, heights, x, y, gid);
754  TileAnimationMapCIter it = tileAnimations.find(gid);
755  if (it != tileAnimations.end())
756  {
757  TileAnimation *const ani = it->second;
758  if (ani != nullptr)
759  ani->addAffectedTile(layer, x + y * w);
760  }
761 
762  x++;
763  if (x == w)
764  {
765  x = 0; y++;
766 
767  // When we're done, don't crash on too much data
768  if (y == h)
769  break;
770  }
771  }
772  }
773  else
774  {
775  for (int i = 0; i < binLen - 3; i += 4)
776  {
777  const int gid = binData[i] |
778  binData[i + 1] << 8 |
779  binData[i + 2] << 16 |
780  binData[i + 3] << 24;
781 
782  setTile(map, layer, layerType, heights, x, y, gid);
783 
784  x++;
785  if (x == w)
786  {
787  x = 0; y++;
788 
789  // When we're done, don't crash on too much data
790  if (y == h)
791  break;
792  }
793  }
794  }
795  free(binData);
796  }
797  return true;
798 }
799 
800 bool MapReader::readCsvLayer(XmlNodeConstPtrConst childNode,
801  Map *const map,
802  MapLayer *const layer,
803  const MapLayerTypeT &layerType,
804  MapHeights *const heights,
805  int &restrict x, int &restrict y,
806  const int w, const int h)
807 {
808  if (childNode == nullptr)
809  return false;
810 
811  if (!XmlHaveChildContent(childNode))
812  return true;
813 
814  const char *const xmlChars = XmlChildContent(childNode);
815  const char *const data = reinterpret_cast<const char*>(xmlChars);
816  if (data == nullptr)
817  return false;
818 
819  std::string csv(data);
820  size_t oldPos = 0;
821 
822  const std::map<int, TileAnimation*> &tileAnimations
823  = map->getTileAnimations();
824  const bool hasAnimations = !tileAnimations.empty();
825 
826  if (hasAnimations)
827  {
828  while (oldPos != std::string::npos)
829  {
830  const size_t pos = csv.find_first_of(',', oldPos);
831  if (pos == std::string::npos)
832  return false;
833 
834  const int gid = atoi(csv.substr(oldPos, pos - oldPos).c_str());
835  setTile(map, layer, layerType, heights, x, y, gid);
836  TileAnimationMapCIter it = tileAnimations.find(gid);
837  if (it != tileAnimations.end())
838  {
839  TileAnimation *const ani = it->second;
840  if (ani != nullptr)
841  ani->addAffectedTile(layer, x + y * w);
842  }
843 
844  x++;
845  if (x == w)
846  {
847  x = 0; y++;
848 
849  // When we're done, don't crash on too much data
850  if (y == h)
851  return false;
852  }
853  oldPos = pos + 1;
854  }
855  }
856  else
857  {
858  while (oldPos != std::string::npos)
859  {
860  const size_t pos = csv.find_first_of(',', oldPos);
861  if (pos == std::string::npos)
862  return false;
863 
864  const int gid = atoi(csv.substr(oldPos, pos - oldPos).c_str());
865  setTile(map, layer, layerType, heights, x, y, gid);
866 
867  x++;
868  if (x == w)
869  {
870  x = 0; y++;
871 
872  // When we're done, don't crash on too much data
873  if (y == h)
874  return false;
875  }
876  oldPos = pos + 1;
877  }
878  }
879  return true;
880 }
881 
882 void MapReader::readLayer(XmlNodeConstPtr node, Map *const map)
883 {
884  if (node == nullptr)
885  return;
886 
887  // Layers are not necessarily the same size as the map
888  const int w = XML::getProperty(node, "width", map->getWidth());
889  const int h = XML::getProperty(node, "height", map->getHeight());
890  const int offsetX = XML::getProperty(node, "x", 0);
891  const int offsetY = XML::getProperty(node, "y", 0);
892  std::string name = XML::getProperty(node, "name", "");
893  name = toLower(name);
894 
895  const bool isFringeLayer = (name.substr(0, 6) == "fringe");
896  const bool isCollisionLayer = (name.substr(0, 9) == "collision");
897  const bool isHeightLayer = (name.substr(0, 7) == "heights");
898  const bool isActionsLayer = (name.substr(0, 7) == "actions");
899  int mask = 1;
900  int tileCondition = -1;
901  int conditionLayer = 0;
902 
904  if (isCollisionLayer)
905  layerType = MapLayerType::COLLISION;
906  else if (isHeightLayer)
907  layerType = MapLayerType::HEIGHTS;
908  else if (isActionsLayer)
909  layerType = MapLayerType::ACTIONS;
910 
911  map->indexTilesets();
912 
913  MapLayer *layer = nullptr;
914  MapHeights *heights = nullptr;
915 
916  logger->log("- Loading layer \"%s\"", name.c_str());
917  int x = 0;
918  int y = 0;
919 
920  // Load the tile data
921  for_each_xml_child_node(childNode, node)
922  {
923  if (xmlNameEqual(childNode, "properties"))
924  {
925  for_each_xml_child_node(prop, childNode)
926  {
927  if (!xmlNameEqual(prop, "property"))
928  continue;
929  const std::string pname = XML::getProperty(prop, "name", "");
930  const std::string value = XML::getProperty(prop, "value", "");
931  // ignoring any layer if property Hidden is 1
932  if (pname == "Hidden")
933  {
934  if (value == "1")
935  return;
936  }
937  else if (pname == "Version")
938  {
939  if (value > CHECK_VERSION)
940  return;
941  }
942  else if (pname == "NotVersion")
943  {
944  if (value <= CHECK_VERSION)
945  return;
946  }
947  else if (pname == "Mask")
948  {
949  mask = atoi(value.c_str());
950  }
951  else if (pname == "TileCondition")
952  {
953  tileCondition = atoi(value.c_str());
954  }
955  else if (pname == "ConditionLayer")
956  {
957  conditionLayer = atoi(value.c_str());
958  }
959  else if (pname == "SideView")
960  {
961  if (value != "down")
962  return;
963  }
964  }
965  }
966 
967  if (!xmlNameEqual(childNode, "data"))
968  continue;
969 
970  // Disable for future usage "TileCondition" attribute
971  // if already set ConditionLayer to non zero
972  if (conditionLayer != 0)
973  tileCondition = -1;
974 
975  switch (layerType)
976  {
977  case MapLayerType::TILES:
978  {
979  layer = new MapLayer(name,
980  offsetX, offsetY,
981  w, h,
982  isFringeLayer,
983  mask,
984  tileCondition);
985  map->addLayer(layer);
986  break;
987  }
989  {
990  heights = new MapHeights(w, h);
991  map->addHeights(heights);
992  break;
993  }
994  default:
997  break;
998  }
999 
1000  const std::string encoding =
1001  XML::getProperty(childNode, "encoding", "");
1002  const std::string compression =
1003  XML::getProperty(childNode, "compression", "");
1004 
1005  if (encoding == "base64")
1006  {
1007  if (readBase64Layer(childNode, map, layer, layerType,
1008  heights, compression, x, y, w, h))
1009  {
1010  continue;
1011  }
1012  else
1013  {
1014  return;
1015  }
1016  }
1017  else if (encoding == "csv")
1018  {
1019  if (readCsvLayer(childNode, map, layer, layerType,
1020  heights, x, y, w, h))
1021  {
1022  continue;
1023  }
1024  else
1025  {
1026  return;
1027  }
1028  }
1029  else
1030  {
1031  const std::map<int, TileAnimation*> &tileAnimations
1032  = map->getTileAnimations();
1033  const bool hasAnimations = !tileAnimations.empty();
1034 
1035  // Read plain XML map file
1036  for_each_xml_child_node(childNode2, childNode)
1037  {
1038  if (!xmlNameEqual(childNode2, "tile"))
1039  continue;
1040 
1041  const int gid = XML::getProperty(childNode2, "gid", -1);
1042  setTile(map, layer, layerType, heights, x, y, gid);
1043  if (hasAnimations)
1044  {
1045  TileAnimationMapCIter it = tileAnimations.find(gid);
1046  if (it != tileAnimations.end())
1047  {
1048  TileAnimation *const ani = it->second;
1049  if (ani != nullptr)
1050  ani->addAffectedTile(layer, x + y * w);
1051  }
1052  }
1053 
1054  x++;
1055  if (x == w)
1056  {
1057  x = 0; y++;
1058  if (y >= h)
1059  break;
1060  }
1061  }
1062  }
1063 
1064  if (y < h)
1065  std::cerr << "TOO SMALL!\n";
1066  if (x != 0)
1067  std::cerr << "TOO SMALL!\n";
1068 
1069  // There can be only one data element
1070  break;
1071  }
1072 }
1073 
1075  const std::string &path,
1076  Map *const map)
1077 {
1078  BLOCK_START("MapReader::readTileset")
1079  if (node == nullptr)
1080  {
1081  BLOCK_END("MapReader::readTileset")
1082  return nullptr;
1083  }
1084 
1085  const int firstGid = XML::getProperty(node, "firstgid", 0);
1086  const int margin = XML::getProperty(node, "margin", 0);
1087  const int spacing = XML::getProperty(node, "spacing", 0);
1088  XML::Document* doc = nullptr;
1089  Tileset *set = nullptr;
1090  std::string pathDir(path);
1091  std::map<std::string, std::string> props;
1092 
1093  if (XmlHasProp(node, "source"))
1094  {
1095  std::string filename = XML::getProperty(node, "source", "");
1096  filename = resolveRelativePath(path, filename);
1097 
1098  doc = new XML::Document(filename, UseVirtFs_true, SkipError_false);
1099  node = doc->rootNode();
1100  if (node == nullptr)
1101  {
1102  delete doc;
1103  BLOCK_END("MapReader::readTileset")
1104  return nullptr;
1105  }
1106 
1107  // Reset path to be realtive to the tsx file
1108  pathDir = filename.substr(0, filename.rfind('/') + 1);
1109  }
1110 
1111  const int tw = XML::getProperty(node, "tilewidth", map->getTileWidth());
1112  const int th = XML::getProperty(node, "tileheight", map->getTileHeight());
1113 
1114  for_each_xml_child_node(childNode, node)
1115  {
1116  if (xmlNameEqual(childNode, "image"))
1117  {
1118  // ignore second other <image> tags in tileset
1119  if (set != nullptr)
1120  continue;
1121 
1122  const std::string source = XML::getProperty(
1123  childNode, "source", "");
1124 
1125  if (!source.empty())
1126  {
1127  const std::string sourceResolved = resolveRelativePath(pathDir,
1128  source);
1129 
1130  Image *const tilebmp = Loader::getImage(sourceResolved);
1131 
1132  if (tilebmp != nullptr)
1133  {
1134  set = new Tileset(tilebmp,
1135  tw, th,
1136  firstGid,
1137  margin,
1138  spacing);
1139  tilebmp->decRef();
1140 #ifdef USE_OPENGL
1141  if (MapDB::isEmptyTileset(sourceResolved))
1142  set->setEmpty(true);
1143  if (tilebmp->getType() == ImageType::Image &&
1144  map->haveAtlas() == true &&
1146  {
1147  reportAlways("Error: image '%s' not present in atlas",
1148  source.c_str())
1149  }
1150 #endif // USE_OPENGL
1151  }
1152  else
1153  {
1154  reportAlways("Error: Failed to load tileset (%s)",
1155  source.c_str())
1156  }
1157  }
1158  }
1159  else if (xmlNameEqual(childNode, "properties"))
1160  {
1161  for_each_xml_child_node(propertyNode, childNode)
1162  {
1163  if (!xmlNameEqual(propertyNode, "property"))
1164  continue;
1165  const std::string name = XML::getProperty(
1166  propertyNode, "name", "");
1167  if (!name.empty())
1168  props[name] = XML::getProperty(propertyNode, "value", "");
1169  }
1170  }
1171  else if (xmlNameEqual(childNode, "tile"))
1172  {
1173  bool haveAnimation(false);
1174 
1175  for_each_xml_child_node(tileNode, childNode)
1176  {
1177  const bool isProps = xmlNameEqual(tileNode, "properties");
1178  const bool isAnim = xmlNameEqual(tileNode, "animation");
1179  if (!isProps && !isAnim)
1180  continue;
1181 
1182  const int tileGID = firstGid + XML::getProperty(
1183  childNode, "id", 0);
1184 
1185  Animation *ani = new Animation("from map");
1186 
1187  if (isProps)
1188  {
1189  // read tile properties to a map for simpler handling
1190  StringIntMap tileProperties;
1191  for_each_xml_child_node(propertyNode, tileNode)
1192  {
1193  if (!xmlNameEqual(propertyNode, "property"))
1194  continue;
1195 
1196  haveAnimation = true;
1197  const std::string name = XML::getProperty(
1198  propertyNode, "name", "");
1199  if (!name.empty())
1200  {
1201  const int value = XML::getProperty(
1202  propertyNode, "value", 0);
1203  tileProperties[name] = value;
1204  logger->log("Tile Prop of %d \"%s\" = \"%d\"",
1205  tileGID, name.c_str(), value);
1206  }
1207  }
1208 
1209  // create animation
1210  if (set == nullptr ||
1211  !config.getBoolValue("playMapAnimations"))
1212  {
1213  delete ani;
1214  continue;
1215  }
1216 
1217  for (int i = 0; ; i++)
1218  {
1219  const std::string iStr(toString(i));
1220  StringIntMapCIter iFrame
1221  = tileProperties.find("animation-frame" + iStr);
1222  StringIntMapCIter iDelay
1223  = tileProperties.find("animation-delay" + iStr);
1224  // possible need add random attribute?
1225  if (iFrame != tileProperties.end()
1226  && iDelay != tileProperties.end())
1227  {
1228  ani->addFrame(set->get(iFrame->second),
1229  iDelay->second, 0, 0, 100);
1230  }
1231  else
1232  {
1233  break;
1234  }
1235  }
1236  }
1237  else if (isAnim && !haveAnimation)
1238  {
1239  for_each_xml_child_node(frameNode, tileNode)
1240  {
1241  if (!xmlNameEqual(frameNode, "frame"))
1242  continue;
1243 
1244  if (set != nullptr)
1245  {
1246  const int tileId = XML::getProperty(
1247  frameNode, "tileid", 0);
1248  const int duration = XML::getProperty(
1249  frameNode, "duration", 0) / 10;
1250 
1251  ani->addFrame(set->get(tileId),
1252  duration,
1253  0, 0, 100);
1254  }
1255  }
1256  }
1257 
1258  if (ani->getLength() > 0)
1259  map->addAnimation(tileGID, new TileAnimation(ani));
1260  else
1261  delete2(ani)
1262  }
1263  }
1264  }
1265 
1266  delete doc;
1267 
1268  if (set != nullptr)
1269  set->setProperties(props);
1270  BLOCK_END("MapReader::readTileset")
1271  return set;
1272 }
1273 
1274 Map *MapReader::createEmptyMap(const std::string &restrict filename,
1275  const std::string &restrict realFilename)
1276 {
1277  logger->log1("Creating empty map");
1278  Map *const map = new Map("empty map",
1279  300, 300,
1281  map->setProperty("_filename", realFilename);
1282  map->setProperty("_realfilename", filename);
1283  updateMusic(map);
1284  map->setCustom(true);
1285  MapLayer *layer = new MapLayer("nolayer",
1286  0, 0,
1287  300, 300,
1288  false,
1289  1,
1290  -1);
1291  map->addLayer(layer);
1292  layer = new MapLayer("nolayer",
1293  0, 0,
1294  300, 300,
1295  true,
1296  1,
1297  -1);
1298  map->addLayer(layer);
1299  map->updateDrawLayersList();
1300  map->updateConditionLayers();
1301  map->preCacheLayers();
1302 
1303  return map;
1304 }
1305 
1306 void MapReader::updateMusic(Map *const map)
1307 {
1308  std::string name = map->getProperty("shortName", std::string());
1309  const size_t p = name.rfind('.');
1310  if (p != std::string::npos)
1311  name = name.substr(0, p);
1312  name.append(".ogg");
1313  if (VirtFs::exists(pathJoin(paths.getStringValue("music"), name)))
1314  map->setProperty("music", name);
1315 }
1316 
1317 #ifdef USE_OPENGL
1319 {
1321  return;
1322 
1323  const MapInfo *const info = MapDB::getAtlas(
1324  paths.getStringValue("emptyAtlasName"));
1325  if (info != nullptr)
1326  {
1328  info->atlas,
1329  *info->files);
1330  delete info;
1331  }
1332 }
1333 
1335 {
1336  if (mEmptyAtlas != nullptr)
1337  mEmptyAtlas->decRef();
1338 }
1339 #endif // USE_OPENGL
VirtFs::exists
bool exists(std::string name)
Definition: fs.cpp:123
Loader::getWalkLayer
WalkLayer * getWalkLayer(const std::string &name, Map *const map)
Definition: walklayerloader.cpp:57
anonymous_namespace{stringutils.cpp}::base
unsigned int base
Definition: stringutils.cpp:226
Properties::setProperty
void setProperty(const std::string &name, const std::string &value)
Definition: properties.h:127
Tileset::getFirstGid
int getFirstGid() const
Definition: tileset.h:57
MapHeights
Definition: mapheights.h:30
walklayerloader.h
reportAlways
#define reportAlways(...)
Definition: checkutils.h:252
collisiontype.h
imageloader.h
animation.h
TileAnimation::addAffectedTile
void addAffectedTile(MapLayer *const layer, const int index)
Definition: tileanimation.h:54
StringIntMapCIter
StringIntMap::const_iterator StringIntMapCIter
Definition: stringmap.h:29
Animation::getLength
size_t getLength() const
Definition: animation.h:69
CollisionType::COLLISION_WATER
@ COLLISION_WATER
Definition: collisiontype.h:33
CollisionType::COLLISION_PLAYER_WALL
@ COLLISION_PLAYER_WALL
Definition: collisiontype.h:35
MapReader::loadLayers
static void loadLayers(const std::string &path)
Definition: mapreader.cpp:306
CAST_SIZE
#define CAST_SIZE
Definition: cast.h:33
fs.h
php3_base64_decode
unsigned char * php3_base64_decode(const unsigned char *const string, const int length, int *const ret_length)
Definition: base64.cpp:100
Map::getTileAnimations
const std::map< int, TileAnimation * > & getTileAnimations() const
Definition: map.h:329
TileAnimationMapCIter
TileAnimationMap::const_iterator TileAnimationMapCIter
Definition: tileanimation.h:64
Map::getWidth
int getWidth() const
Definition: map.h:165
BlockType::MONSTERWALL
@ MONSTERWALL
Definition: blocktype.h:37
Map::haveAtlas
bool haveAtlas() const
Definition: map.h:339
ParticleType::Animation
@ Animation
Definition: particletype.h:29
MapReader::loadEmptyAtlas
static void loadEmptyAtlas()
Definition: mapreader.cpp:1318
map.h
Resource
Definition: resource.h:33
CollisionType::COLLISION_AIR
@ COLLISION_AIR
Definition: collisiontype.h:32
Tileset
Definition: tileset.h:33
MapDB::getMapAtlas
const MapInfo * getMapAtlas(const std::string &name)
Definition: mapdb.cpp:212
MapInfo
Definition: mapinfo.h:29
paths
Configuration paths
Definition: configuration.cpp:55
anonymous_namespace{mapreader.cpp}::mKnownLayers
std::map< std::string, xmlNodePtr > mKnownLayers
Definition: mapreader.cpp:80
Catch::toLower
std::string toLower(std::string const &s)
delete2.h
MapReader::readProperties
static void readProperties(const xmlNode *const node, Properties *const props)
Definition: mapreader.cpp:521
MapReader::readBase64Layer
static bool readBase64Layer(const xmlNode *const childNode, Map *const map, MapLayer *const layer, const MapLayerTypeT &layerType, MapHeights *const heights, const std::string &compression, int &x, int &y, const int w, const int h)
Definition: mapreader.cpp:663
Map::addLayer
void addLayer(MapLayer *const layer)
Definition: map.cpp:312
Map::updateDrawLayersList
void updateDrawLayersList()
Definition: map.cpp:1637
SkipError_false
const bool SkipError_false
Definition: skiperror.h:29
podict.h
BlockType::WATER
@ WATER
Definition: blocktype.h:34
ImageType::Image
@ Image
Definition: imagetype.h:28
MapReader::unloadTempLayers
static void unloadTempLayers()
Definition: mapreader.cpp:313
maplayer.h
Image
Definition: image.h:67
MapLayerType::COLLISION
@ COLLISION
Definition: maplayertype.h:33
pathJoin
std::string pathJoin(std::string str1, const std::string &str2)
Definition: stringutils.cpp:1036
BlockType::AIR
@ AIR
Definition: blocktype.h:33
PoDict::getStr
const std::string getStr(const std::string &str)
Definition: podict.cpp:44
BlockType::WALL
@ WALL
Definition: blocktype.h:32
XML::Document
Definition: libxml.h:52
MapDB::isEmptyTileset
bool isEmptyTileset(const std::string &name)
Definition: mapdb.cpp:237
Map::setCustom
void setCustom(const bool b)
Definition: map.h:323
XML
Definition: libxml.cpp:84
delete2
#define delete2(var)
Definition: delete2.h:24
MapReader::readTileset
static Tileset * readTileset(xmlNodePtr node, const std::string &path, Map *const map)
Definition: mapreader.cpp:1074
MapReader::updateMusic
static void updateMusic(Map *const map)
Definition: mapreader.cpp:1306
MapReader
Definition: mapreader.h:40
XML::getProperty
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:173
mapheights.h
bool
Loader::getEmptyAtlas
Resource * getEmptyAtlas(const std::string &name, const StringVect &files)
Definition: emptyatlasloader.cpp:56
MapReader::readCsvLayer
static bool readCsvLayer(const xmlNode *const childNode, Map *const map, MapLayer *const layer, const MapLayerTypeT &layerType, MapHeights *const heights, int &x, int &y, const int w, const int h)
Definition: mapreader.cpp:800
Catch::toString
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
logger
Logger * logger
Definition: logger.cpp:88
MapLayerTypeT
MapLayerType ::T MapLayerTypeT
Definition: maplayertype.h:37
tileset.h
Actions::info
bool info(InputEvent &event)
Definition: commands.cpp:56
if
if(!vert) return
mapreader.h
CAST_U8
#define CAST_U8
Definition: cast.h:26
fileName
std::string fileName
Definition: testmain.cpp:38
Map::indexTilesets
void indexTilesets()
Definition: map.cpp:1414
CollisionType::COLLISION_EMPTY
@ COLLISION_EMPTY
Definition: collisiontype.h:30
emptyatlasloader.h
StringIntMap
std::map< std::string, int > StringIntMap
Definition: stringmap.h:27
checkutils.h
MapLayer
Definition: maplayer.h:48
BlockType::GROUNDTOP
@ GROUNDTOP
Definition: blocktype.h:35
ImageSet::get
Image * get(const size_type i) const
Definition: imageset.cpp:66
Map::getTileWidth
int getTileWidth() const
Definition: map.h:177
base64.h
data
uint32_t data
Definition: maptypeproperty2.h:3
Map::getTilesetWithGid
const Tileset * getTilesetWithGid(const int gid) const
Definition: map.cpp:699
beingcommon.h
Loader::getImage
Image * getImage(const std::string &idPath)
Definition: imageloader.cpp:85
atlasloader.h
PRAGMACLANG6GCC
#define PRAGMACLANG6GCC(str)
Definition: localconsts.h:239
image.h
x
x
Definition: graphics_calcImageRect.hpp:72
UseVirtFs_true
const bool UseVirtFs_true
Definition: usevirtfs.h:29
Image::getType
virtual ImageTypeT getType() const
Definition: image.h:213
MapLayerType::HEIGHTS
@ HEIGHTS
Definition: maplayertype.h:34
CollisionType::COLLISION_MONSTER_WALL
@ COLLISION_MONSTER_WALL
Definition: collisiontype.h:36
CollisionTypeT
CollisionType ::T CollisionTypeT
Definition: collisiontype.h:39
MapLayer::setTile
void setTile(const int x, const int y, Image *const img)
Definition: maplayer.h:77
graphicsManager
GraphicsManager graphicsManager
Definition: graphicsmanager.cpp:114
Configuration::getStringValue
std::string getStringValue(const std::string &key) const
Definition: configuration.cpp:487
MapItemType::MUSIC
@ MUSIC
Definition: mapitemtype.h:37
MapReader::addLayerToList
static void addLayerToList(const std::string &fileName, const SkipError skipError)
Definition: mapreader.cpp:229
GraphicsManager::getUseAtlases
bool getUseAtlases() const
Definition: graphicsmanager.h:139
anonymous_namespace{mapreader.cpp}::mKnownDocs
std::set< XML::Document * > mKnownDocs
Definition: mapreader.cpp:81
Animation
Definition: animation.h:40
Map::addHeights
void addHeights(const MapHeights *const heights)
Definition: map.cpp:1624
Properties::getProperty
const std::string getProperty(const std::string &name, const std::string &def) const
Definition: properties.h:58
graphicsmanager.h
Logger::log1
void log1(const char *const log_text)
Definition: logger.cpp:237
Loader::getAtlas
AtlasResource * getAtlas(const std::string &name, const StringVect &files)
Definition: atlasloader.cpp:55
config
Configuration config
Definition: configuration.cpp:51
MapHeights::setHeight
void setHeight(const int x, const int y, const uint8_t height)
Definition: mapheights.cpp:40
stringmap.h
Map::getHeight
int getHeight() const
Definition: map.h:171
TileAnimation
Definition: tileanimation.h:43
DocIterator
std::set< XML::Document * >::iterator DocIterator
Definition: mapreader.cpp:72
loadXmlDir2
#define loadXmlDir2(name, function, ext, skipError)
Definition: beingcommon.h:49
resolveRelativePath
static std::string resolveRelativePath(std::string base, std::string relative)
Definition: mapreader.cpp:93
main.h
inflateMemory
static int inflateMemory(unsigned char *in, unsigned int inLength, unsigned char *&out, unsigned int &outLength)
Definition: mapreader.cpp:123
CHECK_VERSION
#define CHECK_VERSION
Definition: main.h:44
std
Definition: mseprimitives.h:398
toUpper
std::string & toUpper(std::string &str)
Definition: stringutils.cpp:71
MapReader::readMap
static Map * readMap(const std::string &filename, const std::string &realFilename)
mapdb.h
Resource::decRef
virtual void decRef()
Definition: resource.cpp:49
configuration.h
MapItemType::PORTAL
@ PORTAL
Definition: mapitemtype.h:36
Map
Definition: map.h:71
Map::preCacheLayers
void preCacheLayers()
Definition: map.cpp:1745
restrict
#define restrict
Definition: localconsts.h:164
Map::getTileHeight
int getTileHeight() const
Definition: map.h:183
MapDB::getAtlas
const MapInfo * getAtlas(const std::string &name)
Definition: mapdb.cpp:225
Map::addAnimation
void addAnimation(const int gid, TileAnimation *const animation)
Definition: map.cpp:1690
Map::getVersion
int getVersion() const
Definition: map.h:309
XML::Document::rootNode
xmlNodePtr rootNode()
Definition: libxml.cpp:168
BLOCK_START
#define BLOCK_START(name)
Definition: perfomance.h:78
BlockType::PLAYERWALL
@ PLAYERWALL
Definition: blocktype.h:36
setTile
static void setTile(Map *map, MapLayer *layer, MapLayerTypeT &layerType, MapHeights *heights, int x, int y, int gid)
Definition: mapreader.cpp:558
BLOCK_END
#define BLOCK_END(name)
Definition: perfomance.h:79
CAST_S32
#define CAST_S32
Definition: cast.h:29
MapReader::unloadEmptyAtlas
static void unloadEmptyAtlas()
Definition: mapreader.cpp:1334
tileanimation.h
Tileset::setProperties
void setProperties(const std::map< std::string, std::string > &props)
Definition: tileset.h:63
new
#define new
Definition: debug_new.h:147
Properties
Definition: properties.h:34
Animation::addFrame
void addFrame(Image *const image, const int delay, const int offsetX, const int offsetY, const int rand)
Definition: animation.cpp:45
CollisionType::COLLISION_WALL
@ COLLISION_WALL
Definition: collisiontype.h:31
BlockType::GROUND
@ GROUND
Definition: blocktype.h:31
A_FALLTHROUGH
#define A_FALLTHROUGH
Definition: localconsts.h:192
for_each_xml_child_node
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:160
Tileset::setEmpty
void setEmpty(const bool b)
Definition: tileset.h:96
CollisionType::COLLISION_GROUNDTOP
@ COLLISION_GROUNDTOP
Definition: collisiontype.h:34
Tileset::isEmpty
bool isEmpty() const
Definition: tileset.h:99
MapLayerType::ACTIONS
@ ACTIONS
Definition: maplayertype.h:35
LayerInfoIterator
std::map< std::string, xmlNodePtr >::iterator LayerInfoIterator
Definition: mapreader.cpp:71
mapitemtype.h
MapReader::createEmptyMap
static Map * createEmptyMap(const std::string &filename, const std::string &realFilename)
Definition: mapreader.cpp:1274
y
y
Definition: graphics_calcImageRect.hpp:72
dirSeparator
const char * dirSeparator
Definition: fs.cpp:42
A_NONNULL
#define A_NONNULL(...)
Definition: localconsts.h:167
translator
PoDict * translator
Definition: podict.cpp:27
loadReplaceLayer
static void loadReplaceLayer(LayerInfoIterator &it, Map *map)
Definition: mapreader.cpp:323
Map::updateConditionLayers
void updateConditionLayers()
Definition: map.cpp:1731
CollisionType::COLLISION_MAX
@ COLLISION_MAX
Definition: collisiontype.h:37
MapReader::mEmptyAtlas
static Resource * mEmptyAtlas
Definition: mapreader.h:119
Logger::log
void log(const char *const log_text,...)
Definition: logger.cpp:268
FOR_EACH
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
debug.h
MapReader::readLayer
static void readLayer(const xmlNodePtr node, Map *const map)
Definition: mapreader.cpp:882
Image::decRef
void decRef()
Definition: image.cpp:522
MapLayerType::TILES
@ TILES
Definition: maplayertype.h:32
mapTileSize
static const int mapTileSize
Definition: map.h:26
VirtFs::read
int64_t read(File *const file, void *const buffer, const uint32_t objSize, const uint32_t objCount)
Definition: fs.cpp:814
Configuration::getBoolValue
bool getBoolValue(const std::string &key) const
Definition: configuration.cpp:596
Map::addBlockMask
void addBlockMask(const int x, const int y, const BlockTypeT type)
Definition: map.cpp:706