33#include <boost/filesystem/operations.hpp>
37#include <unordered_map>
38#include <unordered_set>
70std::unordered_map<std::string, WMODoodadData>
WmoDoodads;
76#define CASC_LOCALES_COUNT 17
92 CASC_LOCALE_ENUS | CASC_LOCALE_ENGB,
102 CASC_LOCALE_PTBR | CASC_LOCALE_PTPT,
112 boost::filesystem::path
const casc_cache_dir(boost::filesystem::canonical(
input_path) /
"CascCache");
117 printf(
"Unable to open remote casc fallback to local casc\n");
120 boost::filesystem::path
const storage_dir(boost::filesystem::canonical(
input_path) /
"Data");
124 printf(
"error opening casc storage '%s' locale %s\n", storage_dir.string().c_str(),
localeNames[locale]);
130 catch (boost::filesystem::filesystem_error
const& error)
132 printf(
"error opening casc storage : %s\n", error.what());
143 boost::filesystem::path
const casc_cache_dir(boost::filesystem::canonical(
input_path) /
"CascCache");
147 return CASC_LOCALE_ALL_WOW;
149 printf(
"Unable to open remote casc fallback to local casc\n");
152 boost::filesystem::path
const storage_dir(boost::filesystem::canonical(
input_path) /
"Data");
157 return storage->GetInstalledLocalesMask();
159 catch (boost::filesystem::filesystem_error
const& error)
161 printf(
"Unable to determine installed locales mask: %s\n", error.what());
174 return uniqueObjectIds.emplace(std::make_pair(clientId, clientDoodadId), newId).first->second;
180 if (FILE* n = fopen(file,
"rb"))
191 std::string originalName = fname;
202 char const* rchr = strrchr(plain_name,
'_');
204 for (
int i = 0; i < 4; ++i)
205 if (isdigit(rchr[i]))
215 printf(
"Couldn't open RootWmo!!!\n");
218 FILE *output = fopen(szLocalFile.c_str(),
"wb");
221 printf(
"couldn't open %s for writing!\n", szLocalFile.c_str());
227 int Wmo_nVertices = 0;
234 if (!fgroup.
open(&froot))
236 printf(
"Could not open all Group file for: %s\n", plain_name);
248 if (groupReference >= doodads.
Spawns.size())
251 uint32 doodadNameIndex = doodads.
Spawns[groupReference].NameIndex;
259 fseek(output, 8, SEEK_SET);
260 fwrite(&Wmo_nVertices,
sizeof(
int), 1, output);
262 fwrite(&groupCount,
sizeof(
uint32), 1, output);
267 remove(szLocalFile.c_str());
273 std::unordered_map<uint32, WDTFile> wdts;
276 auto itr = wdts.find(mapId);
277 if (itr == wdts.end())
279 auto mapEntryItr = std::find_if(
map_ids.begin(),
map_ids.end(), [mapId](
MapEntry const& mapEntry) { return mapEntry.Id == mapId; });
280 if (mapEntryItr ==
map_ids.end())
283 uint32 fileDataId = mapEntryItr->WdtFileDataId;
287 std::string description =
Trinity::StringFormat(
"WDT for map {} - {} (FileDataID {})", mapId, mapEntryItr->Name, fileDataId);
288 std::string directory = mapEntryItr->Directory;
289 itr = wdts.emplace(std::piecewise_construct, std::forward_as_tuple(mapId), std::forward_as_tuple(fileDataId, description, std::move(directory),
maps_that_are_parents.count(mapId) > 0)).first;
290 if (!itr->second.init(mapId))
304 WDTFile* parentWDT = mapEntry.ParentMapID >= 0 ? getWDT(mapEntry.ParentMapID) :
nullptr;
305 printf(
"Processing Map %u\n[", mapEntry.Id);
306 for (
int32 x = 0; x < 64; ++x)
308 for (
int32 y = 0; y < 64; ++y)
310 bool success =
false;
313 success =
ADT->init(mapEntry.Id, mapEntry.Id);
316 if (!success && parentWDT)
320 ADT->init(mapEntry.Id, mapEntry.ParentMapID);
333bool processArgv(
int argc,
char ** argv,
const char *versionString)
338 for (
int i = 1; i < argc; ++i)
340 if (strcmp(
"-s", argv[i]) == 0)
344 else if (strcmp(
"-d", argv[i]) == 0)
348 input_path = boost::filesystem::path(argv[i + 1]);
356 else if (strcmp(
"-?", argv[1]) == 0)
360 else if (strcmp(
"-l", argv[i]) == 0)
364 else if (strcmp(
"-p", argv[i]) == 0)
366 if (i + 1 < argc && strlen(argv[i + 1]))
371 else if (strcmp(
"-c", argv[i]) == 0)
375 else if (strcmp(
"-r", argv[i]) == 0)
377 if (i + 1 < argc && strlen(argv[i + 1]))
382 else if (strcmp(
"-dl", argv[i]) == 0)
384 if (i + 1 < argc && strlen(argv[i + 1]))
403 printf(
"Extract %s.\n",versionString);
404 printf(
"%s [-?][-s][-l][-d <path>][-p <product>]\n", argv[0]);
405 printf(
" -s : (default) small size (data size optimization), ~500MB less vmap data.\n");
406 printf(
" -l : large size, ~500MB more vmap data. (might contain more details)\n");
407 printf(
" -d <path>: Path to the vector data source folder.\n");
408 printf(
" -p <product>: which installed product to open (wow/wowt/wow_beta)\n");
409 printf(
" -c use remote casc\n");
410 printf(
" -r set remote casc region - standard: eu\n");
411 printf(
" -dl dbc locale\n");
412 printf(
" -? : This message.\n");
425 boost::filesystem::path storageDir(boost::filesystem::canonical(
input_path) /
"Data");
426 boost::filesystem::directory_iterator end;
427 for (boost::filesystem::directory_iterator itr(storageDir); itr != end; ++itr)
429 if (itr->path().extension() ==
".MPQ")
431 printf(
"MPQ files found in Data directory!\n");
432 printf(
"This tool works only with World of Warcraft: Battle for Azeroth\n");
434 printf(
"To extract maps for Wrath of the Lich King, rebuild tools using 3.3.5 branch!\n");
436 printf(
"Press ENTER to exit...\n");
442 catch (std::exception
const& error)
444 printf(
"Error checking client version: %s\n", error.what());
450int main(
int argc,
char ** argv)
456 Trinity::Banner::Show(
"VMAP data extractor", [](
char const* text) { printf(
"%s\n", text); },
nullptr);
471 std::string sdir_bin = std::string(
szWorkDirWmo) +
"/dir_bin";
473 if (!stat(sdir.c_str(), &status) || !stat(sdir_bin.c_str(), &status))
475 printf(
"Your output directory seems to be polluted, please use an empty directory!\n");
476 printf(
"<press return to exit>");
478 return scanf(
"%c", garbage);
486#
if defined(__linux__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
490 success = (errno == EEXIST);
493 int32 FirstLocale = -1;
516 printf(
"Detected client build %u for locale %s\n\n", build,
localeNames[i]);
520 if (FirstLocale == -1)
522 printf(
"FATAL ERROR: No locales defined, unable to continue.\n");
533 printf(
"Read Map.dbc file... ");
541 catch (std::exception
const& e)
548 std::unordered_map<uint32, std::size_t> idToIndex;
576 if (itr != idToIndex.end())
591 std::stable_partition(
map_ids.begin(),
map_ids.end(), [](
MapEntry const& map) { return maps_that_are_parents.count(map.Id) > 0; });
char const * localeNames[TOTAL_LOCALES]
char const * GetPlainName(char const *FileName)
void NormalizeFileName(char *name, size_t len)
static Storage * OpenRemote(boost::filesystem::path const &path, uint32 localeMask, char const *product, char const *region)
static Storage * Open(boost::filesystem::path const &path, uint32 localeMask, char const *product)
void Load(DB2FileSource *source, DB2FileLoadInfo const *loadInfo)
DB2Record GetRecord(uint32 recordNumber) const
DB2RecordCopy GetRecordCopy(uint32 copyNumber) const
uint32 GetRecordCopyCount() const
uint32 GetRecordCount() const
int32 GetInt32(uint32 field, uint32 arrayIndex) const
uint16 GetUInt16(uint32 field, uint32 arrayIndex) const
char const * GetString(uint32 field, uint32 arrayIndex) const
void FreeADT(ADTFile *adt)
ADTFile * GetMap(int32 x, int32 y)
std::vector< uint16 > DoodadReferences
bool open(WMORoot *rootWMO)
int ConvertToVMAPGroupWmo(FILE *output, bool preciseVectorData)
bool ShouldSkip(WMORoot const *root) const
std::vector< uint32 > groupFileDataIDs
std::unordered_set< uint32 > ValidDoodadNames
bool ConvertToVMAPRootWmo(FILE *output)
char const * HumanReadableCASCError(uint32 error)
TC_COMMON_API void Show(char const *applicationName, void(*log)(char const *text), void(*logExtraInfo)())
TC_COMMON_API void Init()
TC_COMMON_API void VerifyOsVersion()
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
static constexpr DB2LoadInfo Instance
std::unordered_set< uint16 > References
std::vector< WMO::MODD > Spawns
uint32 GetInstalledLocalesMask()
static bool RetardCheck()
std::unordered_map< std::string, WMODoodadData > WmoDoodads
int main(int argc, char **argv)
std::shared_ptr< CASC::Storage > CascStorage
char const * CascLocaleNames[CASC_LOCALES_COUNT]
uint32 uniqueObjectIdGenerator
uint32 WowLocaleToCascLocaleFlags[12]
boost::filesystem::path input_path
std::map< std::pair< uint32, uint16 >, uint32 > uniqueObjectIds
bool FileExists(char const *file)
bool processArgv(int argc, char **argv, const char *versionString)
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId, bool isWmo)
bool OpenCascStorage(int locale)
std::vector< MapEntry > map_ids
#define CASC_LOCALES_COUNT
char const * szWorkDirWmo
std::unordered_set< uint32 > maps_that_are_parents
bool ExtractSingleWmo(std::string &fname)