From af8863d722f06153877d289b939b5ba84713621d Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 11 Feb 2014 20:59:12 +0300 Subject: add support for map layer replacments. This can be used for mods. --- src/resources/beingcommon.cpp | 6 ++-- src/resources/beingcommon.h | 24 +++++++++---- src/resources/db/colordb.cpp | 2 +- src/resources/db/itemdb.cpp | 4 ++- src/resources/mapreader.cpp | 82 +++++++++++++++++++++++++++++++++++++------ src/resources/mapreader.h | 16 ++++++--- src/utils/xml.h | 3 ++ 7 files changed, 112 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/resources/beingcommon.cpp b/src/resources/beingcommon.cpp index 7b7a57d9e..388312b34 100644 --- a/src/resources/beingcommon.cpp +++ b/src/resources/beingcommon.cpp @@ -49,7 +49,9 @@ void BeingCommon::readBasicAttributes(BeingInfo *const info, info->setHpBarOffsetY(XML::getProperty(node, "hpBarOffsetY", 0)); } -void BeingCommon::getIncludeFiles(const std::string &dir, StringVect &list) +void BeingCommon::getIncludeFiles(const std::string &dir, + StringVect &list, + const std::string &ext) { const std::string path = dir + "/"; StringVect tempList; @@ -57,7 +59,7 @@ void BeingCommon::getIncludeFiles(const std::string &dir, StringVect &list) FOR_EACH (StringVectCIter, it, tempList) { const std::string &str = *it; - if (findLast(str, ".xml")) + if (findLast(str, ext)) list.push_back(str); } std::sort(list.begin(), list.end()); diff --git a/src/resources/beingcommon.h b/src/resources/beingcommon.h index 6124de5a1..2c9741a2c 100644 --- a/src/resources/beingcommon.h +++ b/src/resources/beingcommon.h @@ -30,11 +30,21 @@ class BeingInfo; #define loadXmlDir(name, function) \ - StringVect listVect; \ - BeingCommon::getIncludeFiles(paths.getStringValue( \ - name), listVect); \ - FOR_EACH (StringVectCIter, itVect, listVect) \ - function(*itVect); + { \ + StringVect listVect; \ + BeingCommon::getIncludeFiles(paths.getStringValue( \ + name), listVect, ".xml"); \ + FOR_EACH (StringVectCIter, itVect, listVect) \ + function(*itVect); \ + } + +#define loadXmlDir2(name, function, ext) \ + { \ + StringVect listVect; \ + BeingCommon::getIncludeFiles(name, listVect, ext); \ + FOR_EACH (StringVectCIter, itVect, listVect) \ + function(*itVect); \ + } namespace BeingCommon { @@ -42,7 +52,9 @@ namespace BeingCommon XmlNodePtrConst node, const std::string &hoverCursor); - void getIncludeFiles(const std::string &dir, StringVect &list); + void getIncludeFiles(const std::string &dir, + StringVect &list, + const std::string &ext); } #endif // RESOURCES_BEINGCOMMON_H diff --git a/src/resources/db/colordb.cpp b/src/resources/db/colordb.cpp index 630c1c902..a358bebe7 100644 --- a/src/resources/db/colordb.cpp +++ b/src/resources/db/colordb.cpp @@ -53,7 +53,7 @@ void ColorDB::load() loadHair(paths.getStringValue("hairColorPatchFile"), colors); StringVect list; BeingCommon::getIncludeFiles(paths.getStringValue( - "hairColorPatchDir"), list); + "hairColorPatchDir"), list, ".xml"); FOR_EACH (StringVectCIter, it2, list) loadHair(*it2, colors); diff --git a/src/resources/db/itemdb.cpp b/src/resources/db/itemdb.cpp index abc164493..931377639 100644 --- a/src/resources/db/itemdb.cpp +++ b/src/resources/db/itemdb.cpp @@ -217,7 +217,9 @@ void ItemDB::load() loadXmlFile(paths.getStringValue("itemsPatchFile"), tagNum); StringVect list; - BeingCommon::getIncludeFiles(paths.getStringValue("itemsPatchDir"), list); + BeingCommon::getIncludeFiles(paths.getStringValue("itemsPatchDir"), + list, + ".xml"); FOR_EACH (StringVectCIter, it, list) loadXmlFile(*it, tagNum); } diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 1e59b1673..5cf6d3337 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -30,6 +30,7 @@ #include "tileset.h" #include "resources/animation.h" +#include "resources/beingcommon.h" #include "resources/image.h" #include "resources/resourcemanager.h" @@ -42,6 +43,15 @@ #include "debug.h" +typedef std::map::iterator LayerInfoIterator; +typedef std::set::iterator DocIterator; + +namespace +{ + std::map mKnownLayers; + std::set mKnownDocs; +} // namespace + static int inflateMemory(unsigned char *restrict const in, const unsigned int inLength, unsigned char *&restrict out, @@ -182,28 +192,47 @@ int inflateMemory(unsigned char *restrict const in, return outLength; } +void MapReader::addLayerToList(const std::string &fileName) +{ + XML::Document *doc = new XML::Document(fileName); + XmlNodePtrConst node = doc->rootNode(); + if (!node) + { + delete doc; + return; + } + + for_each_xml_child_node(childNode, node) + { + if (!xmlNameEqual(childNode, "layer")) + continue; + std::string name = XML::getProperty(childNode, "name", ""); + if (name.empty()) + continue; + name = toLower(name); + logger->log("found patch layer: " + name); + LayerInfoIterator it = mKnownLayers.find(name); + mKnownLayers[name] = childNode; + mKnownDocs.insert(doc); + } +} + Map *MapReader::readMap(const std::string &restrict filename, const std::string &restrict realFilename) { BLOCK_START("MapReader::readMap") logger->log("Attempting to read map %s", realFilename.c_str()); - // Load the file through resource manager - const ResourceManager *const resman = ResourceManager::getInstance(); - int fileSize; - void *const buffer = resman->loadFile(realFilename, fileSize); - Map *map = nullptr; - if (!buffer) + XML::Document doc(realFilename); + if (!doc.isLoaded()) { BLOCK_END("MapReader::readMap") return createEmptyMap(filename, realFilename); } - XML::Document doc(reinterpret_cast(buffer), fileSize); - free(buffer); - XmlNodePtrConst node = doc.rootNode(); + Map *map = nullptr; // Parse the inflated map data if (node) { @@ -231,6 +260,24 @@ Map *MapReader::readMap(const std::string &restrict filename, return map; } +void MapReader::loadLayers(const std::string &path) +{ + loadXmlDir2(path, addLayerToList, ".tmx"); +} + +void MapReader::unloadTempLayers() +{ + FOR_EACH (DocIterator, it, mKnownDocs) + delete (*it); + mKnownLayers.clear(); + mKnownDocs.clear(); +} + +static void loadReplaceLayer(LayerInfoIterator &it, Map *const map) +{ + MapReader::readLayer((*it).second, map); +} + Map *MapReader::readMap(XmlNodePtrConst node, const std::string &path) { if (!node) @@ -256,6 +303,9 @@ Map *MapReader::readMap(XmlNodePtrConst node, const std::string &path) return nullptr; } + logger->log("loading replace layer list"); + loadLayers(path + "_replace.d"); + Map *const map = new Map(w, h, tilew, tileh); const std::string fileName = path.substr(path.rfind("/") + 1); @@ -284,7 +334,18 @@ Map *MapReader::readMap(XmlNodePtrConst node, const std::string &path) } else if (xmlNameEqual(childNode, "layer")) { - readLayer(childNode, map); + std::string name = XML::getProperty(childNode, "name", ""); + name = toLower(name); + LayerInfoIterator it = mKnownLayers.find(name); + if (it == mKnownLayers.end()) + { + readLayer(childNode, map); + } + else + { + logger->log("load replace layer: " + name); + loadReplaceLayer(it, map); + } } else if (xmlNameEqual(childNode, "properties")) { @@ -377,6 +438,7 @@ Map *MapReader::readMap(XmlNodePtrConst node, const std::string &path) map->setActorsFix(0, atoi(map->getProperty("actorsfix").c_str())); map->reduce(); map->setWalkLayer(resman->getWalkLayer(fileName, map)); + unloadTempLayers(); return map; } diff --git a/src/resources/mapreader.h b/src/resources/mapreader.h index 4f84f1a1a..27cbd665b 100644 --- a/src/resources/mapreader.h +++ b/src/resources/mapreader.h @@ -59,6 +59,11 @@ class MapReader final const std::string &restrict realFilename) A_WARN_UNUSED; + /** + * Reads a map layer and adds it to the given map. + */ + static void readLayer(const XmlNodePtr node, Map *const map); + private: /** * Reads the properties element. @@ -70,11 +75,6 @@ class MapReader final static void readProperties(const XmlNodePtrConst node, Properties *const props); - /** - * Reads a map layer and adds it to the given map. - */ - static void readLayer(const XmlNodePtr node, Map *const map); - static bool readBase64Layer(const XmlNodePtrConst childNode, Map *const map, MapLayer *const layer, @@ -100,6 +100,12 @@ class MapReader final Map *const map) A_WARN_UNUSED; static void updateMusic(Map *const map); + + static void addLayerToList(const std::string &fileName); + + static void loadLayers(const std::string &path); + + static void unloadTempLayers(); }; #endif // RESOURCES_MAPREADER_H diff --git a/src/utils/xml.h b/src/utils/xml.h index 5c1fb7605..48d60cda7 100644 --- a/src/utils/xml.h +++ b/src/utils/xml.h @@ -90,6 +90,9 @@ namespace XML */ XmlNodePtr rootNode() A_WARN_UNUSED; + bool isLoaded() const + { return mDoc != nullptr; } + private: xmlDocPtr mDoc; }; -- cgit v1.2.3-70-g09d2