AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
vmapexport.cpp File Reference
#include <cerrno>
#include <cstdio>
#include <list>
#include <map>
#include <sys/stat.h>
#include <vector>
#include "vmapexport.h"
#include "adtfile.h"
#include "dbcfile.h"
#include "mpq_libmpq04.h"
#include "wdtfile.h"
#include "wmo.h"

Go to the source code of this file.

Classes

struct  map_id
 

Macros

#define _CRT_SECURE_NO_DEPRECATE
 
#define MPQ_BLOCK_SIZE   0x1000
 

Functions

uint32 GenerateUniqueObjectId (uint32 clientId, uint16 clientDoodadId)
 
bool FileExists (const char *file)
 
void strToLower (char *str)
 
bool ExtractSingleWmo (std::string &fname)
 
void ParsMapFiles ()
 
void getGamePath ()
 
bool scan_patches (char *scanmatch, std::vector< std::string > &pArchiveNames)
 
bool fillArchiveNameVector (std::vector< std::string > &pArchiveNames)
 
bool processArgv (int argc, char **argv, const char *versionString)
 
int main (int argc, char **argv)
 

Variables

ArchiveSet gOpenArchives
 
std::vector< map_idmap_ids
 
uint32 map_count
 
char output_path [128] = "."
 
char input_path [1024] = "."
 
bool hasInputPathParam = false
 
bool preciseVectorData = false
 
std::unordered_map< std::string, WMODoodadDataWmoDoodads
 
char const * szWorkDirWmo = "./Buildings"
 
std::map< std::pair< uint32, uint16 >, uint32uniqueObjectIds
 

Macro Definition Documentation

◆ _CRT_SECURE_NO_DEPRECATE

#define _CRT_SECURE_NO_DEPRECATE

◆ MPQ_BLOCK_SIZE

#define MPQ_BLOCK_SIZE   0x1000

Function Documentation

◆ ExtractSingleWmo()

bool ExtractSingleWmo ( std::string &  fname)
99{
100 // Copy files from archive
101 std::string originalName = fname;
102
103 char szLocalFile[1024];
104 char* plain_name = GetPlainName(&fname[0]);
105 fixnamen(plain_name, strlen(plain_name));
106 fixname2(plain_name, strlen(plain_name));
107 sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name);
108
109 if (FileExists(szLocalFile))
110 return true;
111
112 int p = 0;
113 // Select root wmo files
114 char const* rchr = strrchr(plain_name, '_');
115 if (rchr != nullptr)
116 {
117 char cpy[4];
118 memcpy(cpy, rchr, 4);
119 for (int m : cpy)
120 {
121 if (isdigit(m))
122 p++;
123 }
124 }
125
126 if (p == 3)
127 return true;
128
129 bool file_ok = true;
130 printf("Extracting %s\n", originalName.c_str());
131 WMORoot froot(originalName);
132 if (!froot.open())
133 {
134 printf("Couldn't open RootWmo!!!\n");
135 return false;
136 }
137 FILE* output = fopen(szLocalFile, "wb");
138 if (!output)
139 {
140 printf("couldn't open %s for writing!\n", szLocalFile);
141 return false;
142 }
143 froot.ConvertToVMAPRootWmo(output);
144 WMODoodadData& doodads = WmoDoodads[plain_name];
145 std::swap(doodads, froot.DoodadData);
146 int Wmo_nVertices = 0;
147 //printf("root has %d groups\n", froot->nGroups);
148 if (froot.nGroups != 0)
149 {
150 for (uint32 i = 0; i < froot.nGroups; ++i)
151 {
152 char temp[1024];
153 strncpy(temp, fname.c_str(), 1024);
154 temp[fname.length() - 4] = 0;
155 char groupFileName[1024];
156 int ret = snprintf(groupFileName, 1024, "%s_%03u.wmo", temp, i);
157 if (ret < 0)
158 {
159 printf("Error when formatting string");
160 return false;
161 }
162 //printf("Trying to open groupfile %s\n",groupFileName);
163
164 string s = groupFileName;
165 WMOGroup fgroup(s);
166 if (!fgroup.open(&froot))
167 {
168 printf("Could not open all Group file for: %s\n", plain_name);
169 file_ok = false;
170 break;
171 }
172
173 Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData);
174 for (uint16 groupReference : fgroup.DoodadReferences)
175 {
176 if (groupReference >= doodads.Spawns.size())
177 continue;
178
179 uint32 doodadNameIndex = doodads.Spawns[groupReference].NameIndex;
180 if (froot.ValidDoodadNames.find(doodadNameIndex) == froot.ValidDoodadNames.end())
181 continue;
182
183 doodads.References.insert(groupReference);
184 }
185 }
186 }
187
188 fseek(output, 8, SEEK_SET); // store the correct no of vertices
189 fwrite(&Wmo_nVertices, sizeof(int), 1, output);
190 fclose(output);
191
192 // Delete the extracted file in the case of an error
193 if (!file_ok)
194 remove(szLocalFile);
195 return true;
196}
std::uint32_t uint32
Definition: Define.h:108
std::uint16_t uint16
Definition: Define.h:109
void fixnamen(char *name, size_t len)
Definition: adtfile.cpp:45
void fixname2(char *name, size_t len)
Definition: adtfile.cpp:63
char const * GetPlainName(char const *FileName)
Definition: adtfile.cpp:27
std::unordered_map< std::string, WMODoodadData > WmoDoodads
Definition: vmapexport.cpp:64
bool preciseVectorData
Definition: vmapexport.cpp:63
bool FileExists(const char *file)
Definition: vmapexport.cpp:79
char const * szWorkDirWmo
Definition: vmapexport.cpp:68
Definition: wmo.h:71
std::unordered_set< uint16 > References
Definition: wmo.h:75
std::vector< WMO::MODD > Spawns
Definition: wmo.h:74
Definition: wmo.h:79
Definition: wmo.h:118

References WMOGroup::ConvertToVMAPGroupWmo(), WMORoot::ConvertToVMAPRootWmo(), WMORoot::DoodadData, WMOGroup::DoodadReferences, FileExists(), fixname2(), fixnamen(), GetPlainName(), WMORoot::nGroups, WMORoot::open(), WMOGroup::open(), preciseVectorData, WMODoodadData::References, WMODoodadData::Spawns, szWorkDirWmo, WMORoot::ValidDoodadNames, and WmoDoodads.

Referenced by ExtractGameobjectModels(), ADTFile::init(), and WDTFile::init().

◆ FileExists()

bool FileExists ( const char *  file)
80{
81 if (FILE* n = fopen(file, "rb"))
82 {
83 fclose(n);
84 return true;
85 }
86 return false;
87}

Referenced by ExtractSingleWmo().

◆ fillArchiveNameVector()

bool fillArchiveNameVector ( std::vector< std::string > &  pArchiveNames)
268{
270 getGamePath();
271
272 printf("\nGame path: %s\n", input_path);
273
274 char path[512];
275 string in_path(input_path);
276 std::vector<std::string> locales, searchLocales;
277
278 searchLocales.emplace_back("enGB");
279 searchLocales.emplace_back("enUS");
280 searchLocales.emplace_back("deDE");
281 searchLocales.emplace_back("esES");
282 searchLocales.emplace_back("frFR");
283 searchLocales.emplace_back("koKR");
284 searchLocales.emplace_back("zhCN");
285 searchLocales.emplace_back("zhTW");
286 searchLocales.emplace_back("enCN");
287 searchLocales.emplace_back("enTW");
288 searchLocales.emplace_back("esMX");
289 searchLocales.emplace_back("ruRU");
290
291 for (auto & searchLocale : searchLocales)
292 {
293 std::string localePath = in_path + searchLocale;
294 // check if locale exists:
295 struct stat status;
296 if (stat(localePath.c_str(), &status))
297 continue;
298 if ((status.st_mode & S_IFDIR) == 0)
299 continue;
300 printf("Found locale '%s'\n", searchLocale.c_str());
301 locales.push_back(searchLocale);
302 }
303 printf("\n");
304
305 // open locale expansion and common files
306 printf("Adding data files from locale directories.\n");
307 for (auto & locale : locales)
308 {
309 pArchiveNames.push_back(in_path + locale + "/locale-" + locale + ".MPQ");
310 pArchiveNames.push_back(in_path + locale + "/expansion-locale-" + locale + ".MPQ");
311 pArchiveNames.push_back(in_path + locale + "/lichking-locale-" + locale + ".MPQ");
312 }
313
314 // open expansion and common files
315 pArchiveNames.push_back(input_path + string("common.MPQ"));
316 pArchiveNames.push_back(input_path + string("common-2.MPQ"));
317 pArchiveNames.push_back(input_path + string("expansion.MPQ"));
318 pArchiveNames.push_back(input_path + string("lichking.MPQ"));
319
320 // now, scan for the patch levels in the core dir
321 printf("Scanning patch levels from data directory.\n");
322 int ret = snprintf(path, 512, "%spatch", input_path);
323 if (ret < 0)
324 {
325 printf("Error when formatting string");
326 return false;
327 }
328 if (!scan_patches(path, pArchiveNames))
329 return (false);
330
331 // now, scan for the patch levels in locale dirs
332 printf("Scanning patch levels from locale directories.\n");
333 bool foundOne = false;
334 for (auto & locale : locales)
335 {
336 printf("Locale: %s\n", locale.c_str());
337 int ret2 = snprintf(path, 512, "%s%s/patch-%s", input_path, locale.c_str(), locale.c_str());
338 if (ret2 < 0)
339 {
340 printf("Error when formatting string");
341 return false;
342 }
343 if (scan_patches(path, pArchiveNames))
344 foundOne = true;
345 }
346
347 printf("\n");
348
349 if (!foundOne)
350 {
351 printf("no locale found\n");
352 return false;
353 }
354
355 return true;
356}
bool hasInputPathParam
Definition: vmapexport.cpp:62
void getGamePath()
Definition: vmapexport.cpp:228
char input_path[1024]
Definition: vmapexport.cpp:61
bool scan_patches(char *scanmatch, std::vector< std::string > &pArchiveNames)
Definition: vmapexport.cpp:237

References getGamePath(), hasInputPathParam, input_path, and scan_patches().

Referenced by main().

◆ GenerateUniqueObjectId()

uint32 GenerateUniqueObjectId ( uint32  clientId,
uint16  clientDoodadId 
)
73{
74 return uniqueObjectIds.emplace(std::make_pair(clientId, clientDoodadId), uint32(uniqueObjectIds.size() + 1)).first->second;
75}
std::map< std::pair< uint32, uint16 >, uint32 > uniqueObjectIds
Definition: vmapexport.cpp:70

References uniqueObjectIds.

Referenced by Doodad::Extract(), MapObject::Extract(), and Doodad::ExtractSet().

◆ getGamePath()

void getGamePath ( )
229{
230#ifdef _WIN32
231 strcpy(input_path, "Data\\");
232#else
233 strcpy(input_path, "Data/");
234#endif
235}

References input_path.

Referenced by fillArchiveNameVector().

◆ main()

int main ( int  argc,
char **  argv 
)
421{
422 bool success = true;
423 const char* versionString = "V4.00 2012_02";
424
425 // Use command line arguments, when some
426 if (!processArgv(argc, argv, versionString))
427 return 1;
428
429 // some simple check if working dir is dirty
430 else
431 {
432 std::string sdir = std::string(szWorkDirWmo) + "/dir";
433 std::string sdir_bin = std::string(szWorkDirWmo) + "/dir_bin";
434 struct stat status;
435 if (!stat(sdir.c_str(), &status) || !stat(sdir_bin.c_str(), &status))
436 {
437 printf("Your output directory seems to be polluted, please use an empty directory!\n");
438 printf("<press return to exit>");
439 char garbage[2];
440 return scanf("%c", garbage);
441 }
442 }
443
444 printf("Extract %s. Beginning work ....\n", versionString);
445 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
446 // Create the working directory
447 if (mkdir(szWorkDirWmo
448#if defined(__linux__) || defined(__APPLE__)
449 , 0711
450#endif
451 ))
452 success = (errno == EEXIST);
453
454 // prepare archive name list
455 std::vector<std::string> archiveNames;
456 fillArchiveNameVector(archiveNames);
457 for (auto & archiveName : archiveNames)
458 {
459 MPQArchive* archive = new MPQArchive(archiveName.c_str());
460 if (gOpenArchives.empty() || gOpenArchives.front() != archive)
461 delete archive;
462 }
463
464 if (gOpenArchives.empty())
465 {
466 printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n", input_path);
467 return 1;
468 }
469
470 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
471 //map.dbc
472 if (success)
473 {
474 DBCFile* dbc = new DBCFile("DBFilesClient\\Map.dbc");
475 if (!dbc->open())
476 {
477 delete dbc;
478 printf("FATAL ERROR: Map.dbc not found in data file.\n");
479 return 1;
480 }
481 map_count = dbc->getRecordCount();
482 map_ids.resize(map_count);
483 for (unsigned int x = 0; x < map_count; ++x)
484 {
485 map_ids[x].id = dbc->getRecord(x).getUInt(0);
486
487 char const* map_name = dbc->getRecord(x).getString(1);
488 size_t max_map_name_length = sizeof(map_ids[x].name);
489 if (strlen(map_name) >= max_map_name_length)
490 {
491 delete dbc;
492 printf("FATAL ERROR: Map name too long.\n");
493 return 1;
494 }
495
496 strncpy(map_ids[x].name, map_name, max_map_name_length);
497 map_ids[x].name[max_map_name_length - 1] = '\0';
498 printf("Map - %s\n", map_ids[x].name);
499 }
500
501 delete dbc;
502 ParsMapFiles();
503 //nError = ERROR_SUCCESS;
504 // Extract models, listed in DameObjectDisplayInfo.dbc
506 }
507
508 printf("\n");
509 if (!success)
510 {
511 printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n", versionString, preciseVectorData);
512 getchar();
513 }
514
515 printf("Extract %s. Work complete. No errors.\n", versionString);
516 return 0;
517}
void ExtractGameobjectModels()
Definition: gameobject_extract.cpp:60
std::vector< map_id > map_ids
Definition: vmapexport.cpp:58
bool fillArchiveNameVector(std::vector< std::string > &pArchiveNames)
Definition: vmapexport.cpp:267
void ParsMapFiles()
Definition: vmapexport.cpp:198
uint32 map_count
Definition: vmapexport.cpp:59
ArchiveSet gOpenArchives
Definition: mpq_libmpq.cpp:22
bool processArgv(int argc, char **argv, const char *versionString)
Definition: vmapexport.cpp:358
Definition: dbcfile.h:26
Record getRecord(size_t id)
Definition: dbcfile.cpp:72
bool open()
Definition: dbcfile.cpp:30
size_t getRecordCount() const
Trivial.
Definition: dbcfile.h:125
unsigned int getUInt(size_t field) const
Definition: dbcfile.h:61
const char * getString(size_t field) const
Definition: dbcfile.h:71
Definition: mpq_libmpq04.h:33

References ExtractGameobjectModels(), fillArchiveNameVector(), DBCFile::getRecord(), DBCFile::getRecordCount(), DBCFile::Record::getString(), DBCFile::Record::getUInt(), gOpenArchives, input_path, map_count, map_ids, DBCFile::open(), ParsMapFiles(), preciseVectorData, processArgv(), and szWorkDirWmo.

◆ ParsMapFiles()

void ParsMapFiles ( )
199{
200 char fn[512];
201 //char id_filename[64];
202 for (unsigned int i = 0; i < map_count; ++i)
203 {
204 sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
205 WDTFile WDT(fn,map_ids[i].name);
206 if (WDT.init(map_ids[i].id))
207 {
208 printf("Processing Map %u\n[", map_ids[i].id);
209 for (int x = 0; x < 64; ++x)
210 {
211 for (int y = 0; y < 64; ++y)
212 {
213 if (ADTFile* ADT = WDT.GetMap(x, y))
214 {
215 //sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!!
216 ADT->init(map_ids[i].id, x, y);
217 delete ADT;
218 }
219 }
220 printf("#");
221 fflush(stdout);
222 }
223 printf("]\n");
224 }
225 }
226}
Definition: adtfile.h:27
Definition: adtfile.h:54
Definition: wdtfile.h:29

References WDTFile::GetMap(), WDTFile::init(), map_count, and map_ids.

Referenced by main().

◆ processArgv()

bool processArgv ( int  argc,
char **  argv,
const char *  versionString 
)
359{
360 bool result = true;
361 hasInputPathParam = false;
362 preciseVectorData = false;
363
364 for (int i = 1; i < argc; ++i)
365 {
366 if (strcmp("-s", argv[i]) == 0)
367 {
368 preciseVectorData = false;
369 }
370 else if (strcmp("-d", argv[i]) == 0)
371 {
372 if ((i + 1) < argc)
373 {
374 hasInputPathParam = true;
375 strcpy(input_path, argv[i + 1]);
376 if (input_path[strlen(input_path) - 1] != '\\' && input_path[strlen(input_path) - 1] != '/')
377 strcat(input_path, "/");
378 ++i;
379 }
380 else
381 {
382 result = false;
383 }
384 }
385 else if (strcmp("-?", argv[1]) == 0)
386 {
387 result = false;
388 }
389 else if (strcmp("-l", argv[i]) == 0)
390 {
391 preciseVectorData = true;
392 }
393 else
394 {
395 result = false;
396 break;
397 }
398 }
399 if (!result)
400 {
401 printf("Extract %s.\n", versionString);
402 printf("%s [-?][-s][-l][-d <path>]\n", argv[0]);
403 printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n");
404 printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n");
405 printf(" -d <path>: Path to the vector data source folder.\n");
406 printf(" -? : This message.\n");
407 }
408 return result;
409}

References hasInputPathParam, input_path, and preciseVectorData.

Referenced by main().

◆ scan_patches()

bool scan_patches ( char *  scanmatch,
std::vector< std::string > &  pArchiveNames 
)
238{
239 int i;
240 char path[512];
241
242 for (i = 1; i <= 99; i++)
243 {
244 if (i != 1)
245 {
246 sprintf(path, "%s-%d.MPQ", scanmatch, i);
247 }
248 else
249 {
250 sprintf(path, "%s.MPQ", scanmatch);
251 }
252#ifdef __linux__
253 if (FILE* h = fopen64(path, "rb"))
254#else
255 if (FILE* h = fopen(path, "rb"))
256#endif
257 {
258 fclose(h);
259 //matches.push_back(path);
260 pArchiveNames.emplace_back(path);
261 }
262 }
263
264 return (true);
265}

Referenced by fillArchiveNameVector().

◆ strToLower()

void strToLower ( char *  str)
90{
91 while (*str)
92 {
93 *str = tolower(*str);
94 ++str;
95 }
96}

Variable Documentation

◆ gOpenArchives

◆ hasInputPathParam

bool hasInputPathParam = false

◆ input_path

char input_path[1024] = "."

◆ map_count

◆ map_ids

std::vector<map_id> map_ids

Referenced by main(), and ParsMapFiles().

◆ output_path

char output_path[128] = "."

◆ preciseVectorData

bool preciseVectorData = false

◆ szWorkDirWmo

◆ uniqueObjectIds

std::map<std::pair<uint32, uint16>, uint32> uniqueObjectIds

Referenced by GenerateUniqueObjectId().

◆ WmoDoodads

std::unordered_map<std::string, WMODoodadData> WmoDoodads