diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-07-06 01:24:26 +0200 |
---|---|---|
committer | Ovahlord <dreadkiller@gmx.de> | 2024-07-06 15:36:37 +0200 |
commit | e46cad36d2f7858b83b8cf1382655b49b761f63a (patch) | |
tree | 4e389b31bdbad76a724678f0b2acec7b94f790bd /src/tools | |
parent | caf4c02da82e868f7f77f4967d2cee2a5780828a (diff) |
Tools/vmap_extractor: Split temporary dir_bin into multiple files (one per map) to significantly reduce peak memory usage by vmap_assembler
(cherry picked from commit a0f13391a0404d859cf4f8b8dee0c801f2640473)
# Conflicts:
# src/tools/vmap4_extractor/vmapexport.cpp
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/vmap4_assembler/TileAssembler.cpp | 340 | ||||
-rw-r--r-- | src/tools/vmap4_assembler/TileAssembler.h | 4 | ||||
-rw-r--r-- | src/tools/vmap4_assembler/VMapAssembler.cpp | 87 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/adtfile.cpp | 28 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/model.cpp | 6 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/vmapexport.cpp | 21 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wdtfile.cpp | 14 | ||||
-rw-r--r-- | src/tools/vmap4_extractor/wmo.cpp | 3 |
8 files changed, 290 insertions, 213 deletions
diff --git a/src/tools/vmap4_assembler/TileAssembler.cpp b/src/tools/vmap4_assembler/TileAssembler.cpp index dfd905ff6df..e0a3962cf2b 100644 --- a/src/tools/vmap4_assembler/TileAssembler.cpp +++ b/src/tools/vmap4_assembler/TileAssembler.cpp @@ -17,10 +17,13 @@ #include "TileAssembler.h" #include "BoundingIntervalHierarchy.h" +#include "IteratorPair.h" #include "MapTree.h" #include "Memory.h" +#include "StringConvert.h" #include "StringFormat.h" #include "VMapDefinitions.h" +#include <boost/filesystem/directory.hpp> #include <boost/filesystem/operations.hpp> #include <set> @@ -43,143 +46,67 @@ namespace VMAP TileAssembler::TileAssembler(std::string pSrcDirName, std::string pDestDirName) : iDestDir(std::move(pDestDirName)), iSrcDir(std::move(pSrcDirName)) { - boost::filesystem::create_directories(iDestDir); } bool TileAssembler::convertWorld2() { - bool success = readMapSpawns(); - if (!success) + boost::system::error_code ec; + Trinity::IteratorPair dirBin(boost::filesystem::directory_iterator(iSrcDir + "/dir_bin", ec), {}); + if (ec) + { + printf("Failed to open input %s/dir_bin: %s\n", iSrcDir.c_str(), ec.message().c_str()); return false; + } - float constexpr invTileSize = 1.0f / 533.33333f; - - // export Map data - while (!mapData.empty()) + if (!boost::filesystem::create_directories(iDestDir, ec)) { - MapSpawns data = std::move(mapData.front()); - mapData.pop_front(); - - // build global map tree - std::vector<ModelSpawn*> mapSpawns; - mapSpawns.reserve(data.UniqueEntries.size()); - printf("Calculating model bounds for map %u...\n", data.MapId); - for (auto entry = data.UniqueEntries.begin(); entry != data.UniqueEntries.end(); ++entry) + boost::system::error_code existsErr; + if (!boost::filesystem::exists(iDestDir, existsErr)) { - // M2 models don't have a bound set in WDT/ADT placement data, they're not used for LoS but are needed for pathfinding - if (!(entry->second.flags & MOD_HAS_BOUND)) - if (!calculateTransformedBound(entry->second)) - continue; - - mapSpawns.push_back(&entry->second); - spawnedModelFiles.insert(entry->second.name); - - std::map<uint32, std::set<uint32>>& tileEntries = (entry->second.flags & MOD_PARENT_SPAWN) ? data.ParentTileEntries : data.TileEntries; - - G3D::AABox const& bounds = entry->second.iBound; - G3D::Vector2int16 low(int16(bounds.low().x * invTileSize), int16(bounds.low().y * invTileSize)); - G3D::Vector2int16 high(int16(bounds.high().x * invTileSize), int16(bounds.high().y * invTileSize)); - for (int x = low.x; x <= high.x; ++x) - for (int y = low.y; y <= high.y; ++y) - tileEntries[StaticMapTree::packTileID(x, y)].insert(entry->second.ID); + printf("Failed to create output directory %s: %s\n", iDestDir.c_str(), ec.message().c_str()); + return false; } + // else already exists - this is fine, continue + } - printf("Creating map tree for map %u...\n", data.MapId); - BIH pTree; + std::deque<boost::filesystem::path> mapSpawnFiles; + for (boost::filesystem::directory_entry const& directoryEntry : dirBin) + { + if (!boost::filesystem::is_regular_file(directoryEntry)) + continue; - try - { - pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); - } - catch (std::exception& e) - { - printf(R"(Exception "%s" when calling pTree.build)", e.what()); - return false; - } + mapSpawnFiles.push_back(directoryEntry.path()); + } - std::unordered_map<uint32, uint32> modelNodeIdx; - for (uint32 i = 0; i < mapSpawns.size(); ++i) - modelNodeIdx.try_emplace(mapSpawns[i]->ID, i); + // export Map data + while (!mapSpawnFiles.empty()) + { + boost::filesystem::path file = std::move(mapSpawnFiles.front()); + mapSpawnFiles.pop_front(); - // write map tree file - std::string mapfilename = Trinity::StringFormat("{}/{:04}.vmtree", iDestDir, data.MapId); - auto mapfile = Trinity::make_unique_ptr_with_deleter(fopen(mapfilename.c_str(), "wb"), &::fclose); - if (!mapfile) + auto dirf = Trinity::make_unique_ptr_with_deleter(fopen(file.string().c_str(), "rb"), &::fclose); + if (!dirf) { - success = false; - printf("Cannot open %s\n", mapfilename.c_str()); - break; + printf("Could not read dir_bin file!\n"); + return false; } - //general info - if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile.get()) != 8) success = false; - // Nodes - if (success && fwrite("NODE", 4, 1, mapfile.get()) != 1) success = false; - if (success) success = pTree.writeToFile(mapfile.get()); - - mapfile = nullptr; - - // <==== - - // write map tile files, similar to ADT files, only with extra BIH tree node info - for (auto const& [tileId, spawns] : data.TileEntries) + Optional<uint32> mapId = Trinity::StringTo<uint32>(file.filename().string()); + if (!mapId) { - uint32 x, y; - StaticMapTree::unpackTileID(tileId, x, y); - std::string tileFileName = Trinity::StringFormat("{}/{:04}_{:02}_{:02}.vmtile", iDestDir, data.MapId, y, x); - auto tileFile = Trinity::make_unique_ptr_with_deleter(fopen(tileFileName.c_str(), "wb"), &::fclose); - std::string tileSpawnIndicesFileName = Trinity::StringFormat("{}/{:04}_{:02}_{:02}.vmtileidx", iDestDir, data.MapId, y, x); - auto tileSpawnIndicesFile = Trinity::make_unique_ptr_with_deleter(fopen(tileSpawnIndicesFileName.c_str(), "wb"), &::fclose); - if (tileFile && tileSpawnIndicesFile) - { - std::set<uint32> const& parentTileEntries = data.ParentTileEntries[tileId]; - - uint32 nSpawns = spawns.size() + parentTileEntries.size(); - - // file header - if (success && fwrite(VMAP_MAGIC, 1, 8, tileFile.get()) != 8) success = false; - if (success && fwrite(VMAP_MAGIC, 1, 8, tileSpawnIndicesFile.get()) != 8) success = false; - // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tileFile.get()) != 1) success = false; - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) success = false; - // write tile spawns - for (auto spawnItr = spawns.begin(); spawnItr != spawns.end() && success; ++spawnItr) - { - success = ModelSpawn::writeToFile(tileFile.get(), data.UniqueEntries[*spawnItr]); - if (success && fwrite(&modelNodeIdx[*spawnItr], sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) success = false; - } - - for (auto spawnItr = parentTileEntries.begin(); spawnItr != parentTileEntries.end() && success; ++spawnItr) - { - success = ModelSpawn::writeToFile(tileFile.get(), data.UniqueEntries[*spawnItr]); - if (success && fwrite(&modelNodeIdx[*spawnItr], sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) success = false; - } - } + printf("Invalid Map ID %s\n", file.filename().string().c_str()); + return false; } - for (auto const& [tileId, spawns] : data.ParentTileEntries) - { - if (data.TileEntries.contains(tileId)) - continue; + printf("spawning Map %u\n", *mapId); - uint32 x, y; - StaticMapTree::unpackTileID(tileId, x, y); - std::string tileSpawnIndicesFileName = Trinity::StringFormat("{}/{:04}_{:02}_{:02}.vmtileidx", iDestDir, data.MapId, y, x); - auto tileSpawnIndicesFile = Trinity::make_unique_ptr_with_deleter(fopen(tileSpawnIndicesFileName.c_str(), "wb"), &::fclose); - if (tileSpawnIndicesFile) - { - uint32 nSpawns = spawns.size(); - - // file header - if (success && fwrite(VMAP_MAGIC, 1, 8, tileSpawnIndicesFile.get()) != 8) success = false; - // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) success = false; - // write tile spawns - for (auto spawnItr = spawns.begin(); spawnItr != spawns.end() && success; ++spawnItr) - if (fwrite(&modelNodeIdx[*spawnItr], sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) - success = false; - } - } + MapSpawns data; + data.MapId = *mapId; + if (!readMapSpawns(dirf.get(), &data)) + return false; + + if (!convertMap(data)) + return false; } // add an object models, listed in temp_gameobject_models file @@ -192,54 +119,175 @@ namespace VMAP if (!convertRawFile(spawnedModelFile)) { printf("error converting %s\n", spawnedModelFile.c_str()); - success = false; break; } } - return success; + return true; } - bool TileAssembler::readMapSpawns() + bool TileAssembler::convertMap(MapSpawns& data) { - std::string fname = iSrcDir + "/dir_bin"; - auto dirf = Trinity::make_unique_ptr_with_deleter(fopen(fname.c_str(), "rb"), &::fclose); - if (!dirf) + float constexpr invTileSize = 1.0f / 533.33333f; + + // build global map tree + std::vector<ModelSpawn*> mapSpawns; + mapSpawns.reserve(data.UniqueEntries.size()); + printf("Calculating model bounds for map %u...\n", data.MapId); + for (auto& [spawnId, spawn] : data.UniqueEntries) + { + // M2 models don't have a bound set in WDT/ADT placement data, they're not used for LoS but are needed for pathfinding + if (!(spawn.flags & MOD_HAS_BOUND)) + if (!calculateTransformedBound(spawn)) + continue; + + mapSpawns.push_back(&spawn); + spawnedModelFiles.insert(spawn.name); + + std::map<uint32, std::set<uint32>>& tileEntries = (spawn.flags & MOD_PARENT_SPAWN) ? data.ParentTileEntries : data.TileEntries; + + G3D::AABox const& bounds = spawn.iBound; + G3D::Vector2int16 low(int16(bounds.low().x * invTileSize), int16(bounds.low().y * invTileSize)); + G3D::Vector2int16 high(int16(bounds.high().x * invTileSize), int16(bounds.high().y * invTileSize)); + for (int x = low.x; x <= high.x; ++x) + for (int y = low.y; y <= high.y; ++y) + tileEntries[StaticMapTree::packTileID(x, y)].insert(spawnId); + } + + printf("Creating map tree for map %u...\n", data.MapId); + BIH pTree; + + try + { + pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); + } + catch (std::exception& e) { - printf("Could not read dir_bin file!\n"); + printf(R"(Exception "%s" when calling pTree.build)", e.what()); return false; } - printf("Read coordinate mapping...\n"); - uint32 mapID, check; - std::map<uint32, MapSpawns> data; - while (!feof(dirf.get())) + + std::unordered_map<uint32, uint32> modelNodeIdx; + for (uint32 i = 0; i < mapSpawns.size(); ++i) + modelNodeIdx.try_emplace(mapSpawns[i]->ID, i); + + // write map tree file + std::string mapfilename = Trinity::StringFormat("{}/{:04}.vmtree", iDestDir, data.MapId); + auto mapfile = Trinity::make_unique_ptr_with_deleter(fopen(mapfilename.c_str(), "wb"), &::fclose); + if (!mapfile) { - // read mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name - check = fread(&mapID, sizeof(uint32), 1, dirf.get()); - if (check == 0) // EoF... - break; + printf("Cannot open %s\n", mapfilename.c_str()); + return false; + } - ModelSpawn spawn; - if (!ModelSpawn::readFromFile(dirf.get(), spawn)) - break; + //general info + if (fwrite(VMAP_MAGIC, 1, 8, mapfile.get()) != 8) + return false; + // Nodes + if (fwrite("NODE", 4, 1, mapfile.get()) != 1) + return false; + if (!pTree.writeToFile(mapfile.get())) + return false; + + mapfile = nullptr; + + // <==== - auto [itr, isNew] = data.try_emplace(mapID); - if (isNew) + // write map tile files, similar to ADT files, only with extra BIH tree node info + for (auto const& [tileId, spawns] : data.TileEntries) + { + uint32 x, y; + StaticMapTree::unpackTileID(tileId, x, y); + std::string tileFileName = Trinity::StringFormat("{}/{:04}_{:02}_{:02}.vmtile", iDestDir, data.MapId, y, x); + auto tileFile = Trinity::make_unique_ptr_with_deleter(fopen(tileFileName.c_str(), "wb"), &::fclose); + std::string tileSpawnIndicesFileName = Trinity::StringFormat("{}/{:04}_{:02}_{:02}.vmtileidx", iDestDir, data.MapId, y, x); + auto tileSpawnIndicesFile = Trinity::make_unique_ptr_with_deleter(fopen(tileSpawnIndicesFileName.c_str(), "wb"), &::fclose); + if (tileFile && tileSpawnIndicesFile) { - itr->second.MapId = mapID; - printf("spawning Map %u\n", mapID); + std::set<uint32> const& parentTileEntries = data.ParentTileEntries[tileId]; + + uint32 nSpawns = spawns.size() + parentTileEntries.size(); + + // file header + if (fwrite(VMAP_MAGIC, 1, 8, tileFile.get()) != 8) + return false; + if (fwrite(VMAP_MAGIC, 1, 8, tileSpawnIndicesFile.get()) != 8) + return false; + + // write number of tile spawns + if (fwrite(&nSpawns, sizeof(uint32), 1, tileFile.get()) != 1) + return false; + if (fwrite(&nSpawns, sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) + return false; + + // write tile spawns + for (uint32 spawnId : spawns) + { + if (!ModelSpawn::writeToFile(tileFile.get(), data.UniqueEntries[spawnId])) + return false; + if (fwrite(&modelNodeIdx[spawnId], sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) + return false; + } + + for (uint32 spawnId : parentTileEntries) + { + if (!ModelSpawn::writeToFile(tileFile.get(), data.UniqueEntries[spawnId])) + return false; + if (fwrite(&modelNodeIdx[spawnId], sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) + return false; + } } + } - itr->second.UniqueEntries.emplace(spawn.ID, spawn); + for (auto const& [tileId, spawns] : data.ParentTileEntries) + { + if (data.TileEntries.contains(tileId)) + continue; + + uint32 x, y; + StaticMapTree::unpackTileID(tileId, x, y); + std::string tileSpawnIndicesFileName = Trinity::StringFormat("{}/{:04}_{:02}_{:02}.vmtileidx", iDestDir, data.MapId, y, x); + auto tileSpawnIndicesFile = Trinity::make_unique_ptr_with_deleter(fopen(tileSpawnIndicesFileName.c_str(), "wb"), &::fclose); + if (tileSpawnIndicesFile) + { + uint32 nSpawns = spawns.size(); + + // file header + if (fwrite(VMAP_MAGIC, 1, 8, tileSpawnIndicesFile.get()) != 8) + return false; + + // write number of tile spawns + if (fwrite(&nSpawns, sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) + return false; + + // write tile spawns + for (uint32 spawnId : spawns) + if (fwrite(&modelNodeIdx[spawnId], sizeof(uint32), 1, tileSpawnIndicesFile.get()) != 1) + return false; + } } - mapData.resize(data.size()); - auto dst = mapData.begin(); - for (auto src = data.begin(); src != data.end(); ++src, ++dst) - *dst = std::move(src->second); + return true; + } - bool success = (ferror(dirf.get()) == 0); - return success; + bool TileAssembler::readMapSpawns(FILE* dirf, MapSpawns* data) + { + while (!feof(dirf)) + { + // read Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name + ModelSpawn spawn; + if (!ModelSpawn::readFromFile(dirf, spawn)) + { + if (feof(dirf)) + break; + + return false; + } + + data->UniqueEntries.emplace(spawn.ID, spawn); + } + + return true; } bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) diff --git a/src/tools/vmap4_assembler/TileAssembler.h b/src/tools/vmap4_assembler/TileAssembler.h index 5e9c963a0d7..f803793a5b5 100644 --- a/src/tools/vmap4_assembler/TileAssembler.h +++ b/src/tools/vmap4_assembler/TileAssembler.h @@ -94,14 +94,14 @@ namespace VMAP private: std::string iDestDir; std::string iSrcDir; - MapData mapData; std::set<std::string> spawnedModelFiles; public: TileAssembler(std::string pSrcDirName, std::string pDestDirName); bool convertWorld2(); - bool readMapSpawns(); + bool convertMap(MapSpawns& data); + static bool readMapSpawns(FILE* dirf, MapSpawns* data); bool calculateTransformedBound(ModelSpawn &spawn); void exportGameobjectModels(); diff --git a/src/tools/vmap4_assembler/VMapAssembler.cpp b/src/tools/vmap4_assembler/VMapAssembler.cpp index 031a5c8dcb7..b492b207879 100644 --- a/src/tools/vmap4_assembler/VMapAssembler.cpp +++ b/src/tools/vmap4_assembler/VMapAssembler.cpp @@ -15,13 +15,28 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <string> -#include <iostream> - -#include "TileAssembler.h" #include "Banner.h" +#include "GitRevision.h" #include "Locales.h" +#include "Optional.h" +#include "TileAssembler.h" #include "Util.h" +#include <boost/program_options.hpp> +#include <iostream> +#include <string> + +namespace po = boost::program_options; + +/** + * Parses command line arguments + * + * @param [in] argc command line argument count + * @param [in] argv raw command line arguments + * @param [out] src raw data dir + * @param [out] dest vmap dest dir + * @return Non-empty optional if program should exit immediately (holds exit code in that case) + */ +Optional<int> HandleArgs(int argc, char* argv[], std::string* src, std::string* dest); int main(int argc, char* argv[]) { @@ -29,23 +44,11 @@ int main(int argc, char* argv[]) Trinity::Locale::Init(); - Trinity::Banner::Show("VMAP assembler", [](char const* text) { std::cout << text << std::endl; }, nullptr); - - std::string src = "Buildings"; - std::string dest = "vmaps"; + std::string src, dest; + if (Optional<int> exitCode = HandleArgs(argc, argv, &src, &dest)) + return *exitCode; - if (argc > 3) - { - std::cout << "usage: " << argv[0] << " <raw data dir> <vmap dest dir>" << std::endl; - return 1; - } - else - { - if (argc > 1) - src = argv[1]; - if (argc > 2) - dest = argv[2]; - } + Trinity::Banner::Show("VMAP assembler", [](char const* text) { std::cout << text << std::endl; }, nullptr); std::cout << "using " << src << " as source directory and writing output to " << dest << std::endl; @@ -60,3 +63,47 @@ int main(int argc, char* argv[]) std::cout << "Ok, all done" << std::endl; return 0; } + +Optional<int> HandleArgs(int argc, char* argv[], std::string* src, std::string* dest) +{ + po::options_description visible("Usage: vmap4assembler [OPTION]... [SRC] [DEST]\n\nWhere OPTION can be any of"); + visible.add_options() + ("help,h", "print usage message") + ("version,v", "print version build info"); + + po::options_description all; + all.add(visible); + all.add_options() + ("src", po::value(src)->default_value("Buildings"), "raw data dir") + ("dest", po::value(dest)->default_value("vmaps"), "vmap dest dir"); + + po::positional_options_description positional; + positional.add("src", 1); + positional.add("dest", 1); + + po::variables_map variablesMap; + try + { + store(po::command_line_parser(argc, argv).options(all).positional(positional).run(), variablesMap); + notify(variablesMap); + } + catch (std::exception& e) + { + std::cerr << e.what() << '\n'; + return 1; + } + + if (variablesMap.contains("help")) + { + std::cout << visible << '\n'; + return 0; + } + + if (variablesMap.contains("version")) + { + std::cout << GitRevision::GetFullVersion() << '\n'; + return 0; + } + + return {}; +} diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index 2af001f1751..44b1198bbeb 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -20,6 +20,7 @@ #include "StringFormat.h" #include <cstdio> #include "Errors.h" +#include "Memory.h" char const* GetPlainName(char const* FileName) { @@ -105,8 +106,8 @@ bool ADTFile::init(uint32 map_num, uint32 originalMapId) return false; uint32 size; - std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; - FILE* dirfile = fopen(dirname.c_str(), "ab"); + std::string dirname = Trinity::StringFormat("{}/dir_bin/{:04}", szWorkDirWmo, map_num); + auto dirfile = Trinity::make_unique_ptr_with_deleter(fopen(dirname.c_str(), "ab"), &::fclose); if(!dirfile) { printf("Can't open dirfile!'%s'\n", dirname.c_str()); @@ -184,13 +185,13 @@ bool ADTFile::init(uint32 map_num, uint32 originalMapId) _file.read(&doodadDef, sizeof(ADT::MDDF)); if (!(doodadDef.Flags & 0x40)) { - Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, originalMapId, dirfile, dirfileCache); + Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, originalMapId, dirfile.get(), dirfileCache); } else { std::string fileName = Trinity::StringFormat("FILE{:08X}.xxx", doodadDef.Id); ExtractSingleModel(fileName); - Doodad::Extract(doodadDef, fileName.c_str(), map_num, originalMapId, dirfile, dirfileCache); + Doodad::Extract(doodadDef, fileName.c_str(), map_num, originalMapId, dirfile.get(), dirfileCache); } } @@ -208,15 +209,15 @@ bool ADTFile::init(uint32 map_num, uint32 originalMapId) _file.read(&mapObjDef, sizeof(ADT::MODF)); if (!(mapObjDef.Flags & 0x8)) { - MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), false, map_num, originalMapId, dirfile, dirfileCache); - Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, false, map_num, originalMapId, dirfile, dirfileCache); + MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), false, map_num, originalMapId, dirfile.get(), dirfileCache); + Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, false, map_num, originalMapId, dirfile.get(), dirfileCache); } else { std::string fileName = Trinity::StringFormat("FILE{:08X}.xxx", mapObjDef.Id); ExtractSingleWmo(fileName); - MapObject::Extract(mapObjDef, fileName.c_str(), false, map_num, originalMapId, dirfile, dirfileCache); - Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, false, map_num, originalMapId, dirfile, dirfileCache); + MapObject::Extract(mapObjDef, fileName.c_str(), false, map_num, originalMapId, dirfile.get(), dirfileCache); + Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, false, map_num, originalMapId, dirfile.get(), dirfileCache); } } @@ -229,7 +230,6 @@ bool ADTFile::init(uint32 map_num, uint32 originalMapId) } _file.close(); - fclose(dirfile); return true; } @@ -238,8 +238,8 @@ bool ADTFile::initFromCache(uint32 map_num, uint32 originalMapId) if (dirfileCache->empty()) return true; - std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; - FILE* dirfile = fopen(dirname.c_str(), "ab"); + std::string dirname = Trinity::StringFormat("{}/dir_bin/{:04}", szWorkDirWmo, map_num); + auto dirfile = Trinity::make_unique_ptr_with_deleter(fopen(dirname.c_str(), "ab"), &::fclose); if (!dirfile) { printf("Can't open dirfile!'%s'\n", dirname.c_str()); @@ -248,15 +248,13 @@ bool ADTFile::initFromCache(uint32 map_num, uint32 originalMapId) for (ADTOutputCache const& cached : *dirfileCache) { - fwrite(&map_num, sizeof(uint32), 1, dirfile); uint8 flags = cached.Flags; if (map_num != originalMapId) flags |= MOD_PARENT_SPAWN; - fwrite(&flags, sizeof(uint8), 1, dirfile); - fwrite(cached.Data.data(), cached.Data.size(), 1, dirfile); + fwrite(&flags, sizeof(uint8), 1, dirfile.get()); + fwrite(cached.Data.data(), cached.Data.size(), 1, dirfile.get()); } - fclose(dirfile); return true; } diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index f1272cb28a6..af2eafe4bf6 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -184,8 +184,7 @@ void Doodad::Extract(ADT::MDDF const& doodadDef, char const* ModelInstName, uint if (mapID != originalMapId) tcflags |= MOD_PARENT_SPAWN; - //write mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, name - fwrite(&mapID, sizeof(uint32), 1, pDirfile); + //write Flags, NameSet, UniqueId, Pos, Rot, Scale, name fwrite(&tcflags, sizeof(uint8), 1, pDirfile); fwrite(&nameSet, sizeof(uint8), 1, pDirfile); fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); @@ -292,8 +291,7 @@ void Doodad::ExtractSet(WMODoodadData const& doodadData, ADT::MODF const& wmo, b if (mapID != originalMapId) tcflags |= MOD_PARENT_SPAWN; - //write mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, name - fwrite(&mapID, sizeof(uint32), 1, pDirfile); + //write Flags, NameSet, UniqueId, Pos, Rot, Scale, name fwrite(&tcflags, sizeof(uint8), 1, pDirfile); fwrite(&nameSet, sizeof(uint8), 1, pDirfile); fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 2724289bd8a..f9903c7222b 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -40,12 +40,6 @@ #include <vector> #include <cstdio> #include <cerrno> -#include <sys/stat.h> - -#ifdef _WIN32 - #include <direct.h> - #define mkdir _mkdir -#endif //----------------------------------------------------------------------------- @@ -472,12 +466,10 @@ int main(int argc, char ** argv) return 1; // some simple check if working dir is dirty - else + boost::filesystem::path sdir_bin = boost::filesystem::path(szWorkDirWmo) / "dir_bin"; { - std::string sdir = std::string(szWorkDirWmo) + "/dir"; - std::string sdir_bin = std::string(szWorkDirWmo) + "/dir_bin"; - struct stat status; - if (!stat(sdir.c_str(), &status) || !stat(sdir_bin.c_str(), &status)) + boost::system::error_code ec; + if (boost::filesystem::exists(sdir_bin, ec) && !boost::filesystem::is_empty(sdir_bin, ec)) { printf("Your output directory seems to be polluted, please use an empty directory!\n"); printf("<press return to exit>"); @@ -489,12 +481,7 @@ int main(int argc, char ** argv) printf("Extract %s. Beginning work ....\n", VMAP::VMAP_MAGIC); //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // Create the working directory - if (mkdir(szWorkDirWmo -#if defined(__linux__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - , 0711 -#endif - )) - success = (errno == EEXIST); + success = boost::filesystem::create_directories(sdir_bin) || boost::filesystem::is_directory(sdir_bin); uint32 installedLocalesMask = GetInstalledLocalesMask(); int32 FirstLocale = -1; diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index ec7a2168bec..43778067f1b 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -20,6 +20,7 @@ #include "adtfile.h" #include "Common.h" #include "Errors.h" +#include "Memory.h" #include "StringFormat.h" #include <cstdio> @@ -49,8 +50,8 @@ bool WDTFile::init(uint32 mapId) char fourcc[5]; uint32 size; - std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; - FILE* dirfile = fopen(dirname.c_str(), "ab"); + std::string dirname = Trinity::StringFormat("{}/dir_bin/{:04}", szWorkDirWmo, mapId); + auto dirfile = Trinity::make_unique_ptr_with_deleter(fopen(dirname.c_str(), "ab"), &::fclose); if (!dirfile) { printf("Can't open dirfile!'%s'\n", dirname.c_str()); @@ -117,15 +118,15 @@ bool WDTFile::init(uint32 mapId) _file.read(&mapObjDef, sizeof(ADT::MODF)); if (!(mapObjDef.Flags & 0x8)) { - MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), true, mapId, mapId, dirfile, nullptr); - Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, true, mapId, mapId, dirfile, nullptr); + MapObject::Extract(mapObjDef, _wmoNames[mapObjDef.Id].c_str(), true, mapId, mapId, dirfile.get(), nullptr); + Doodad::ExtractSet(WmoDoodads[_wmoNames[mapObjDef.Id]], mapObjDef, true, mapId, mapId, dirfile.get(), nullptr); } else { std::string fileName = Trinity::StringFormat("FILE{:08X}.xxx", mapObjDef.Id); ExtractSingleWmo(fileName); - MapObject::Extract(mapObjDef, fileName.c_str(), true, mapId, mapId, dirfile, nullptr); - Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, true, mapId, mapId, dirfile, nullptr); + MapObject::Extract(mapObjDef, fileName.c_str(), true, mapId, mapId, dirfile.get(), nullptr); + Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, true, mapId, mapId, dirfile.get(), nullptr); } } } @@ -134,7 +135,6 @@ bool WDTFile::init(uint32 mapId) } _file.close(); - fclose(dirfile); return true; } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index d883ab3597e..ddf669b0141 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -628,8 +628,7 @@ void MapObject::Extract(ADT::MODF const& mapObjDef, char const* WmoInstName, boo if (mapID != originalMapId) flags |= MOD_PARENT_SPAWN; - //write mapID, Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name - fwrite(&mapID, sizeof(uint32), 1, pDirfile); + //write Flags, NameSet, UniqueId, Pos, Rot, Scale, Bound_lo, Bound_hi, name fwrite(&flags, sizeof(uint8), 1, pDirfile); fwrite(&nameSet, sizeof(uint8), 1, pDirfile); fwrite(&uniqueId, sizeof(uint32), 1, pDirfile); |