/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "adtfile.h"
#include "DB2CascFileSource.h"
#include "Errors.h"
#include "ExtractorDB2LoadInfo.h"
#include "model.h"
#include "StringFormat.h"
#include "vmapexport.h"
#include "VMapDefinitions.h"
#include
#include
#include
#include "advstd.h"
bool ExtractSingleModel(std::string& fname)
{
if (fname.length() < 4)
return false;
std::string extension = fname.substr(fname.length() - 4, 4);
if (extension == ".mdx" || extension == ".MDX" || extension == ".mdl" || extension == ".MDL")
{
fname.erase(fname.length() - 2, 2);
fname.append("2");
}
std::string originalName = fname;
char* name = GetPlainName((char*)fname.c_str());
NormalizeFileName(name, strlen(name));
std::string output(szWorkDirWmo);
output += "/";
output += name;
if (FileExists(output.c_str()))
return true;
Model mdl(originalName);
if (!mdl.open())
return false;
return mdl.ConvertToVMAPModel(output.c_str());
}
extern std::shared_ptr CascStorage;
bool GetHeaderMagic(std::string const& fileName, std::array* magic)
{
*magic = { };
std::unique_ptr file(CascStorage->OpenFile(fileName.c_str(), CASC_LOCALE_ALL_WOW));
if (!file)
return false;
uint32 bytesToRead = uint32(magic->size() * sizeof(std::remove_pointer_t::value_type));
uint32 bytesRead = 0;
if (!file->ReadFile(magic->data(), bytesToRead, &bytesRead) || bytesRead != bytesToRead)
return false;
return true;
}
void ExtractGameobjectModels()
{
printf("Extracting GameObject models...\n");
DB2CascFileSource source(CascStorage, GameobjectDisplayInfoLoadInfo::Instance.Meta->FileDataId);
DB2FileLoader db2;
try
{
db2.Load(&source, &GameobjectDisplayInfoLoadInfo::Instance);
}
catch (std::exception const& e)
{
printf("Fatal error: Invalid GameObjectDisplayInfo.db2 file format!\n%s\n", e.what());
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;
}
fwrite(VMAP::RAW_VMAP_MAGIC, 1, 8, model_list);
for (uint32 rec = 0; rec < db2.GetRecordCount(); ++rec)
{
DB2Record record = db2.GetRecord(rec);
if (!record)
continue;
uint32 fileId = record.GetUInt32("FileDataID");
if (!fileId)
continue;
std::string fileName = Trinity::StringFormat("FILE{:08X}.xxx", fileId);
bool result = false;
std::array headerRaw;
if (!GetHeaderMagic(fileName, &headerRaw))
continue;
std::string_view header(headerRaw.data(), headerRaw.size());
if (header == "REVM")
result = ExtractSingleWmo(fileName);
else if (header == "MD20" || header == "MD21")
result = ExtractSingleModel(fileName);
else if (header == "BLP2")
continue; // broken db2 data
else
ABORT_MSG("%s header: 0x%X%X%X%X - " STRING_VIEW_FMT, fileName.c_str(),
uint32(headerRaw[3]), uint32(headerRaw[2]), uint32(headerRaw[1]), uint32(headerRaw[0]),
STRING_VIEW_FMT_ARG(header));
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");
}