39 #include "resources/map/map.h"
86 const unsigned int inLength,
91 const unsigned int inLength,
97 size_t i =
base.length();
98 if (
base.at(i - 1) ==
'/')
101 while (relative.substr(0, 3) ==
"../")
103 relative.erase(0, 3);
106 i =
base.find_last_of(
'/');
107 if (i == std::string::npos)
117 return base + relative;
125 const unsigned int inLength,
129 int bufferSize = 256 * 1024;
130 out =
static_cast<unsigned char*
>(calloc(bufferSize, 1));
133 strm.zalloc =
nullptr;
134 strm.zfree =
nullptr;
135 strm.opaque =
nullptr;
137 strm.avail_in = inLength;
139 strm.avail_out = bufferSize;
143 int ret = inflateInit2(&strm, 15 + 32);
151 if (strm.next_out ==
nullptr)
157 ret = inflate(&strm, Z_NO_FLUSH);
158 if (ret == Z_STREAM_ERROR)
168 (void) inflateEnd(&strm);
174 if (ret != Z_STREAM_END)
176 out =
static_cast<unsigned char*
>(realloc(out, bufferSize * 2));
184 strm.next_out = out +
CAST_SIZE(bufferSize);
185 strm.avail_out = bufferSize;
189 while (ret != Z_STREAM_END);
191 outLength = bufferSize - strm.avail_out;
192 (void) inflateEnd(&strm);
197 const unsigned int inLength,
200 unsigned int outLength = 0;
203 if (ret != Z_OK || (out ==
nullptr))
205 if (ret == Z_MEM_ERROR)
207 reportAlways(
"Error: Out of memory while decompressing map data!")
209 else if (ret == Z_VERSION_ERROR)
213 else if (ret == Z_DATA_ERROR)
219 reportAlways(
"Error: Unknown error while decompressing map data!")
236 XmlNodePtrConst node = doc->
rootNode();
246 if (!xmlNameEqual(childNode,
"layer"))
252 logger->
log(
"found patch layer: " + name);
262 const std::string &
restrict realFilename)
265 logger->log("Attempting to
read map %s", realFilename.c_str());
274 XmlNodePtrConst node = doc.rootNode();
280 if (!xmlNameEqual(node,
"map"))
281 logger->
log(
"Error: Not a map file (%s)!", realFilename.c_str());
283 map =
readMap(node, realFilename);
288 realFilename.c_str())
293 map->setProperty(
"_filename", realFilename);
294 map->setProperty(
"_realfilename", filename);
296 if (map->getProperty(
"music", std::string()).empty())
299 map->updateConditionLayers();
300 map->preCacheLayers();
337 const
std::
string pathDir = path.substr(0, path.rfind('/') + 1);
344 const
bool showWarps =
config.getBoolValue("warpParticle");
346 paths.getStringValue("portalEffectFile"));
348 if (tilew < 0 || tileh < 0)
351 "Uninitialized tile width or height value for map: %s",
357 logger->log("loading replace layer list");
364 map->screenResized();
367 map->setProperty("shortName",
fileName);
386 BLOCK_END(
"MapReader::readMap load atlas")
391 if (xmlNameEqual(childNode,
"tileset"))
394 if (tileset !=
nullptr)
395 map->addTileset(tileset);
397 else if (xmlNameEqual(childNode,
"layer"))
408 logger->
log(
"load replace layer: " + name);
412 else if (xmlNameEqual(childNode,
"properties"))
415 map->setVersion(atoi(map->getProperty(
416 "manaplus version", std::string()).c_str()));
418 else if (xmlNameEqual(childNode,
"objectgroup"))
423 const int offsetX = tileOffsetX * tilew;
424 const int offsetY = tileOffsetY * tileh;
425 const bool showParticles =
430 if (xmlNameEqual(objectNode,
"object"))
433 objectNode,
"type",
"");
448 objectNode,
"name",
"");
454 logger->
log(
"- Loading object name: %s type: %s at %d:%d"
455 " (%dx%d)", objName.c_str(), objType.c_str(),
456 objX, objY, objW, objH);
458 if (objType ==
"PARTICLE_EFFECT")
462 logger->
log1(
" Warning: No particle file given");
468 map->addParticleEffect(objName,
476 logger->
log(
"Ignore particle effect: " + objName);
479 else if (objType ==
"WARP")
483 map->addParticleEffect(warpPath,
484 objX, objY, objW, objH);
487 objX, objY, objW, objH);
489 else if (objType ==
"SPAWN")
496 else if (objType ==
"MUSIC")
499 objX, objY, objW, objH);
503 logger->
log1(
" Warning: Unknown object type");
510 map->initializeAmbientLayers();
511 map->clearIndexedTilesets();
513 atoi(map->getProperty(
"actorsfix", std::string()).c_str()));
517 map->updateDrawLayersList();
534 if (!xmlNameEqual(childNode,
"property"))
541 if (!name.empty() && !value.empty())
546 props->setProperty(name, value);
556 const int x,
const int y,
563 const int x,
const int y,
571 if (layer ==
nullptr)
573 if (set !=
nullptr &&
594 if (collisionId < 0 ||
642 if (set ==
nullptr || heights ==
nullptr)
652 if (layer !=
nullptr)
669 const std::string &compression,
671 const int w,
const int h)
673 if (childNode ==
nullptr)
676 if (!compression.empty() && compression !=
"gzip"
677 && compression !=
"zlib")
680 " compression supported!")
685 if (!XmlHaveChildContent(childNode))
688 const size_t len = strlen(XmlChildContent(childNode)) + 1;
689 unsigned char *charData =
new unsigned char[len + 1];
690 const char *
const xmlChars = XmlChildContent(childNode);
691 const char *charStart =
reinterpret_cast<const char*
>(xmlChars);
692 if (charStart ==
nullptr)
698 unsigned char *charIndex = charData;
700 while (*charStart != 0)
702 if (*charStart !=
' ' &&
703 *charStart !=
'\t' &&
706 *charIndex = *charStart;
715 CAST_S32(strlen(
reinterpret_cast<char*
>(
716 charData))), &binLen);
721 if (binData !=
nullptr)
723 if (compression ==
"gzip" || compression ==
"zlib")
726 unsigned char *inflated =
nullptr;
727 const unsigned int inflatedSize =
732 binLen = inflatedSize;
734 if (inflated ==
nullptr)
741 const std::map<int, TileAnimation*> &tileAnimations
744 const bool hasAnimations = !tileAnimations.empty();
747 for (
int i = 0; i < binLen - 3; i += 4)
749 const int gid = binData[i] |
750 binData[i + 1] << 8 |
751 binData[i + 2] << 16 |
752 binData[i + 3] << 24;
754 setTile(map, layer, layerType, heights,
x,
y, gid);
756 if (it != tileAnimations.end())
776 for (
int i = 0; i < binLen - 3; i += 4)
778 const int gid = binData[i] |
779 binData[i + 1] << 8 |
780 binData[i + 2] << 16 |
781 binData[i + 3] << 24;
783 setTile(map, layer, layerType, heights,
x,
y, gid);
807 const int w,
const int h)
809 if (childNode ==
nullptr)
812 if (!XmlHaveChildContent(childNode))
815 const char *
const xmlChars = XmlChildContent(childNode);
816 const char *
const data =
reinterpret_cast<const char*
>(xmlChars);
820 std::string csv(
data);
823 const std::map<int, TileAnimation*> &tileAnimations
825 const bool hasAnimations = !tileAnimations.empty();
829 while (oldPos != std::string::npos)
831 const size_t pos = csv.find_first_of(
',', oldPos);
832 if (pos == std::string::npos)
835 const int gid = atoi(csv.substr(oldPos, pos - oldPos).c_str());
836 setTile(map, layer, layerType, heights,
x,
y, gid);
838 if (it != tileAnimations.end())
859 while (oldPos != std::string::npos)
861 const size_t pos = csv.find_first_of(
',', oldPos);
862 if (pos == std::string::npos)
865 const int gid = atoi(csv.substr(oldPos, pos - oldPos).c_str());
866 setTile(map, layer, layerType, heights,
x,
y, gid);
896 const bool isFringeLayer = (name.substr(0, 6) ==
"fringe");
897 const bool isCollisionLayer = (name.substr(0, 9) ==
"collision");
898 const bool isHeightLayer = (name.substr(0, 7) ==
"heights");
899 const bool isActionsLayer = (name.substr(0, 7) ==
"actions");
901 int tileCondition = -1;
902 int conditionLayer = 0;
905 if (isCollisionLayer)
907 else if (isHeightLayer)
909 else if (isActionsLayer)
917 logger->
log(
"- Loading layer \"%s\"", name.c_str());
924 if (xmlNameEqual(childNode,
"properties"))
928 if (!xmlNameEqual(prop,
"property"))
933 if (pname ==
"Hidden")
938 else if (pname ==
"Version")
943 else if (pname ==
"NotVersion")
948 else if (pname ==
"Mask")
950 mask = atoi(value.c_str());
952 else if (pname ==
"TileCondition")
954 tileCondition = atoi(value.c_str());
956 else if (pname ==
"ConditionLayer")
958 conditionLayer = atoi(value.c_str());
960 else if (pname ==
"SideView")
968 if (!xmlNameEqual(childNode,
"data"))
973 if (conditionLayer != 0)
1001 const std::string encoding =
1003 const std::string compression =
1006 if (encoding ==
"base64")
1009 heights, compression,
x,
y, w, h))
1018 else if (encoding ==
"csv")
1021 heights,
x,
y, w, h))
1032 const std::map<int, TileAnimation*> &tileAnimations
1034 const bool hasAnimations = !tileAnimations.empty();
1039 if (!xmlNameEqual(childNode2,
"tile"))
1043 setTile(map, layer, layerType, heights,
x,
y, gid);
1047 if (it != tileAnimations.end())
1066 std::cerr <<
"TOO SMALL!\n";
1068 std::cerr <<
"TOO SMALL!\n";
1076 const std::string &path,
1080 if (node ==
nullptr)
1091 std::string pathDir(path);
1092 std::map<std::string, std::string> props;
1094 if (XmlHasProp(node,
"source"))
1101 if (node ==
nullptr)
1109 pathDir = filename.substr(0, filename.rfind(
'/') + 1);
1117 if (xmlNameEqual(childNode,
"image"))
1124 childNode,
"source",
"");
1126 if (!source.empty())
1133 if (tilebmp !=
nullptr)
1160 else if (xmlNameEqual(childNode,
"properties"))
1164 if (!xmlNameEqual(propertyNode,
"property"))
1167 propertyNode,
"name",
"");
1172 else if (xmlNameEqual(childNode,
"tile"))
1174 bool haveAnimation(
false);
1178 const bool isProps = xmlNameEqual(tileNode,
"properties");
1179 const bool isAnim = xmlNameEqual(tileNode,
"animation");
1180 if (!isProps && !isAnim)
1184 childNode,
"id", 0);
1194 if (!xmlNameEqual(propertyNode,
"property"))
1197 haveAnimation =
true;
1199 propertyNode,
"name",
"");
1203 propertyNode,
"value", 0);
1204 tileProperties[name] = value;
1205 logger->
log(
"Tile Prop of %d \"%s\" = \"%d\"",
1206 tileGID, name.c_str(), value);
1211 if (set ==
nullptr ||
1218 for (
int i = 0; ; i++)
1220 const std::string iStr(
toString(i));
1222 = tileProperties.find(
"animation-frame" + iStr);
1224 = tileProperties.find(
"animation-delay" + iStr);
1226 if (iFrame != tileProperties.end()
1227 && iDelay != tileProperties.end())
1230 iDelay->second, 0, 0, 100);
1238 else if (isAnim && !haveAnimation)
1242 if (!xmlNameEqual(frameNode,
"frame"))
1248 frameNode,
"tileid", 0);
1250 frameNode,
"duration", 0) / 10;
1276 const std::string &
restrict realFilename)
1279 Map *
const map =
new Map(
"empty map",
1309 std::string name = map->
getProperty(
"shortName", std::string());
1310 const size_t p = name.rfind(
'.');
1311 if (p != std::string::npos)
1312 name = name.substr(0, p);
1313 name.append(
".ogg");
1326 if (
info !=
nullptr)
unsigned char * php3_base64_decode(const unsigned char *const string, const int length, int *const ret_length)
#define loadXmlDir2(name, function, ext, skipError)
#define reportAlways(...)
void addFrame(Image *const image, const int delay, const int offsetX, const int offsetY, const int rand)
bool getBoolValue(const std::string &key) const
std::string getStringValue(const std::string &key) const
bool getUseAtlases() const
Image * get(const size_type i) const
void log(const char *const log_text,...)
void log1(const char *const log_text)
void setHeight(const int x, const int y, const uint8_t height)
void setTile(const int x, const int y, Image *const img)
static void readProperties(const xmlNode *const node, Properties *const props)
static void loadLayers(const std::string &path)
static Map * createEmptyMap(const std::string &filename, const std::string &realFilename)
static Tileset * readTileset(xmlNodePtr node, const std::string &path, Map *const map)
static Resource * mEmptyAtlas
static void updateMusic(Map *const map)
static void unloadEmptyAtlas()
static void addLayerToList(const std::string &fileName, const SkipError skipError)
static Map * readMap(const std::string &filename, const std::string &realFilename)
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)
static void readLayer(const xmlNodePtr node, Map *const map)
static void unloadTempLayers()
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)
static void loadEmptyAtlas()
void updateConditionLayers()
void addLayer(MapLayer *const layer)
int getTileHeight() const
void setCustom(const bool b)
void addBlockMask(const int x, const int y, const BlockTypeT type)
const std::map< int, TileAnimation * > & getTileAnimations() const
void updateDrawLayersList()
void addHeights(const MapHeights *const heights)
void addAnimation(const int gid, TileAnimation *const animation)
const Tileset * getTilesetWithGid(const int gid) const
const std::string getStr(const std::string &str)
void setProperty(const std::string &name, const std::string &value)
const std::string getProperty(const std::string &name, const std::string &def) const
void addAffectedTile(MapLayer *const layer, const int index)
void setEmpty(const bool b)
void setProperties(const std::map< std::string, std::string > &props)
CollisionType ::T CollisionTypeT
static const int mapTileSize
const char * dirSeparator
#define FOR_EACH(type, iter, array)
GraphicsManager graphicsManager
#define for_each_xml_child_node(var, parent)
#define PRAGMACLANG6GCC(str)
MapLayerType ::T MapLayerTypeT
static int inflateMemory(unsigned char *in, unsigned int inLength, unsigned char *&out, unsigned int &outLength)
static void setTile(Map *map, MapLayer *layer, MapLayerTypeT &layerType, MapHeights *heights, int x, int y, int gid)
std::set< XML::Document * >::iterator DocIterator
static void loadReplaceLayer(LayerInfoIterator &it, Map *map)
std::map< std::string, xmlNodePtr >::iterator LayerInfoIterator
static std::string resolveRelativePath(std::string base, std::string relative)
bool info(InputEvent &event)
std::string toLower(std::string const &s)
std::string toString(T const &value)
converts any type to a string
WalkLayer * getWalkLayer(const std::string &name, Map *const map)
Resource * getEmptyAtlas(const std::string &name, const StringVect &files)
Image * getImage(const std::string &idPath)
AtlasResource * getAtlas(const std::string &name, const StringVect &files)
const MapInfo * getMapAtlas(const std::string &name)
const MapInfo * getAtlas(const std::string &name)
bool isEmptyTileset(const std::string &name)
int64_t read(File *const file, void *const buffer, const uint32_t objSize, const uint32_t objCount)
bool exists(std::string name)
int getProperty(const xmlNodePtr node, const char *const name, int def)
std::set< XML::Document * > mKnownDocs
std::map< std::string, xmlNodePtr > mKnownLayers
#define BLOCK_START(name)
const bool SkipError_false
std::map< std::string, int > StringIntMap
StringIntMap::const_iterator StringIntMapCIter
std::string & toUpper(std::string &str)
std::string pathJoin(std::string str1, const std::string &str2)
TileAnimationMap::const_iterator TileAnimationMapCIter
const bool UseVirtFs_true