void ExtractGameobjectModels() { printf("Extracting GameObject models...\n"); DB2CascFileSource source(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.db2"); DB2FileLoader db2; if (!db2.Load(&source, GameobjectDisplayInfoLoadInfo::Instance())) { printf("Fatal error: Invalid GameObjectDisplayInfo.db2 file format!\n"); exit(1); } std::string basepath = szWorkDirWmo; basepath += "/"; std::string modelListPath = basepath + "temp_gameobject_models"; FILE* model_list = fopen(modelListPath.c_str(), "wb"); if (!model_list) { printf("Fatal error: Could not open file %s\n", modelListPath.c_str()); return; } for (uint32 rec = 0; rec < db2.GetRecordCount(); ++rec) { DB2Record record = db2.GetRecord(rec); uint32 fileId = record.GetUInt32(0, 0); if (!fileId) continue; std::string fileName = Trinity::StringFormat("FILE%08X.xxx", fileId); bool result = false; uint32 header; if (!GetHeaderMagic(fileName, &header)) continue; if (header == MODEL_WMO) result = ExtractSingleWmo(fileName); else if (header == MODEL_MD20 || header == MODEL_MD21) result = ExtractSingleModel(fileName); else ASSERT(false, "%s header: %d - %c%c%c%c", fileName.c_str(), header, (header >> 24) & 0xFF, (header >> 16) & 0xFF, (header >> 8) & 0xFF, header & 0xFF); if (result) { uint32 displayId = record.GetId(); uint32 path_length = fileName.length(); fwrite(&displayId, sizeof(uint32), 1, model_list); fwrite(&path_length, sizeof(uint32), 1, model_list); fwrite(fileName.c_str(), sizeof(char), path_length, model_list); } } fclose(model_list); printf("Done!\n"); }
int main(int argc, char ** argv) { Trinity::Banner::Show("VMAP data extractor", [](char const* text) { printf("%s\n", text); }, nullptr); bool success = true; const char *versionString = "V4.06 2018_02"; // Use command line arguments, when some if (!processArgv(argc, argv, versionString)) return 1; if (!RetardCheck()) return 1; // some simple check if working dir is dirty else { 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)) { printf("Your output directory seems to be polluted, please use an empty directory!\n"); printf("<press return to exit>"); char garbage[2]; return scanf("%c", garbage); } } printf("Extract %s. Beginning work ....\n\n", versionString); //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // Create the working directory if (mkdir(szWorkDirWmo #if defined(__linux__) || defined(__APPLE__) , 0711 #endif )) success = (errno == EEXIST); uint32 installedLocalesMask = GetInstalledLocalesMask(); int32 FirstLocale = -1; for (int i = 0; i < TOTAL_LOCALES; ++i) { if (i == LOCALE_none) continue; if (!(installedLocalesMask & WowLocaleToCascLocaleFlags[i])) continue; if (!OpenCascStorage(i)) continue; FirstLocale = i; uint32 build = CASC::GetBuildNumber(CascStorage); if (!build) { CascStorage.reset(); continue; } printf("Detected client build: %u\n\n", build); break; } if (FirstLocale == -1) { printf("FATAL ERROR: No locales defined, unable to continue.\n"); return 1; } // Extract models, listed in GameObjectDisplayInfo.dbc ExtractGameobjectModels(); //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx //map.dbc if (success) { printf("Read Map.dbc file... "); DB2CascFileSource source(CascStorage, "DBFilesClient\\Map.db2"); DB2FileLoader db2; if (!db2.Load(&source, MapLoadInfo::Instance())) { printf("Fatal error: Invalid Map.db2 file format! %s\n", CASC::HumanReadableCASCError(GetLastError())); exit(1); } for (uint32 x = 0; x < db2.GetRecordCount(); ++x) { DB2Record record = db2.GetRecord(x); map_info& m = map_ids[record.GetId()]; const char* map_name = record.GetString("Directory"); size_t max_map_name_length = sizeof(m.name); if (strlen(map_name) >= max_map_name_length) { printf("Fatal error: Map name too long!\n"); exit(1); } strncpy(m.name, map_name, max_map_name_length); m.name[max_map_name_length - 1] = '\0'; m.parent_id = int16(record.GetUInt16("ParentMapID")); if (m.parent_id >= 0) maps_that_are_parents.insert(m.parent_id); } for (uint32 x = 0; x < db2.GetRecordCopyCount(); ++x) { DB2RecordCopy copy = db2.GetRecordCopy(x); auto itr = map_ids.find(copy.SourceRowId); if (itr != map_ids.end()) { map_info& id = map_ids[copy.NewRowId]; strcpy(id.name, itr->second.name); id.parent_id = itr->second.parent_id; } } printf("Done! (" SZFMTD " maps loaded)\n", map_ids.size()); ParsMapFiles(); } CascStorage.reset(); printf("\n"); if (!success) { printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n", versionString, preciseVectorData); getchar(); } printf("Extract %s. Work complete. No errors.\n", versionString); return 0; }