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 uint32 groupCount = 0;
148 //printf("root has %d groups\n", froot->nGroups);
149 if (froot.nGroups != 0)
150 {
151 for (uint32 i = 0; i < froot.nGroups; ++i)
152 {
153 char temp[1024];
154 strncpy(temp, fname.c_str(), 1024);
155 temp[fname.length() - 4] = 0;
156 char groupFileName[1024];
157 int ret = snprintf(groupFileName, 1024, "%s_%03u.wmo", temp, i);
158 if (ret < 0)
159 {
160 printf("Error when formatting string");
161 return false;
162 }
163 //printf("Trying to open groupfile %s\n",groupFileName);
164
165 string s = groupFileName;
166 WMOGroup fgroup(s);
167 if (!fgroup.open(&froot))
168 {
169 printf("Could not open all Group file for: %s\n", plain_name);
170 file_ok = false;
171 break;
172 }
173
174 if (fgroup.ShouldSkip(&froot))
175 continue;
176
177 Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData);
178 ++groupCount;
179 for (uint16 groupReference : fgroup.DoodadReferences)
180 {
181 if (groupReference >= doodads.Spawns.size())
182 continue;
183
184 uint32 doodadNameIndex = doodads.Spawns[groupReference].NameIndex;
185 if (froot.ValidDoodadNames.find(doodadNameIndex) == froot.ValidDoodadNames.end())
186 continue;
187
188 doodads.References.insert(groupReference);
189 }
190 }
191 }
192
193 fseek(output, 8, SEEK_SET); // store the correct no of vertices
194 fwrite(&Wmo_nVertices, sizeof(int), 1, output);
195 // store the correct no of groups
196 fwrite(&groupCount, sizeof(uint32), 1, output);
197 fclose(output);
198
199 // Delete the extracted file in the case of an error
200 if (!file_ok)
201 remove(szLocalFile);
202 return true;
203}
std::uint32_t uint32
Definition Define.h:107
std::uint16_t uint16
Definition Define.h:108
char const * GetPlainName(char const *FileName)
Definition adtfile.cpp:26
void fixnamen(char *name, std::size_t len)
Definition adtfile.cpp:44
void fixname2(char *name, std::size_t len)
Definition adtfile.cpp:62
Definition wmo.h:119
Definition wmo.h:79
Definition wmo.h:71
std::unordered_set< uint16 > References
Definition wmo.h:75
std::vector< WMO::MODD > Spawns
Definition wmo.h:74
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

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

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 ( )
236{
237#ifdef _WIN32
238 strcpy(input_path, "Data\\");
239#else
240 strcpy(input_path, "Data/");
241#endif
242}

References input_path.

Referenced by fillArchiveNameVector().

◆ main()

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

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 ( )
206{
207 char fn[512];
208 //char id_filename[64];
209 for (unsigned int i = 0; i < map_count; ++i)
210 {
211 sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
212 WDTFile WDT(fn,map_ids[i].name);
213 if (WDT.init(map_ids[i].id))
214 {
215 printf("Processing Map %u\n[", map_ids[i].id);
216 for (int x = 0; x < 64; ++x)
217 {
218 for (int y = 0; y < 64; ++y)
219 {
220 if (ADTFile* ADT = WDT.GetMap(x, y))
221 {
222 //sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!!
223 ADT->init(map_ids[i].id, x, y);
224 delete ADT;
225 }
226 }
227 printf("#");
228 fflush(stdout);
229 }
230 printf("]\n");
231 }
232 }
233}
Definition adtfile.h:54
Definition wdtfile.h:28
Definition adtfile.h:27

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

Referenced by main().

◆ processArgv()

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

References hasInputPathParam, input_path, and preciseVectorData.

Referenced by main().

◆ scan_patches()

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

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