Improved vmap-extractor.

- Problem: duplicates. The current version of the extractor truncates the wmo/m2 filenames, removing the path component in the process. But this leads to duplicates (for example "world\wmo\transports\zeppelin" and "world\wmo\transports\transport-zeppelin" both have transport-zeppelin.wmo as rootwmo).
  - To circumvent this, I compute a md5 hash for the path component and prefix it to the name of the resource, using a "GetUniformName" routine.
This commit is contained in:
H0zen 2015-09-10 06:22:17 +03:00
parent 7cbeac65d4
commit 25e241b4b8
11 changed files with 283 additions and 405 deletions

View File

@ -32,11 +32,11 @@ include_directories(
add_executable(${EXECUTABLE_NAME} ${EXECUTABLE_SRCS}
adtfile.cpp
dbcfile.cpp
gameobject_extract.cpp
model.cpp
vmapexport.cpp
wdtfile.cpp
wmo.cpp
${CMAKE_SOURCE_DIR}/src/shared/Auth/md5.c
)
target_link_libraries(${EXECUTABLE_NAME} libmpq loadlib bzip2 zlib)

View File

@ -32,85 +32,30 @@
#define snprintf _snprintf
#endif
const char* GetPlainName(const char* FileName)
{
const char* szTemp;
if ((szTemp = strrchr(FileName, '\\')) != NULL)
{ FileName = szTemp + 1; }
return FileName;
}
char* GetPlainName(char* FileName)
{
char* szTemp;
if ((szTemp = strrchr(FileName, '\\')) != NULL)
{ FileName = szTemp + 1; }
return FileName;
}
void fixnamen(char* name, size_t len)
{
for (size_t i = 0; i < len - 3; i++)
{
if (i > 0 && name[i] >= 'A' && name[i] <= 'Z' && isalpha(name[i - 1]))
{
name[i] |= 0x20;
}
else if ((i == 0 || !isalpha(name[i - 1])) && name[i] >= 'a' && name[i] <= 'z')
{
name[i] &= ~0x20;
}
}
//extension in lowercase
for (size_t i = len - 3; i < len; i++)
{ name[i] |= 0x20; }
}
void fixname2(char* name, size_t len)
{
for (size_t i = 0; i < len - 3; i++)
{
if (name[i] == ' ')
{ name[i] = '_'; }
}
}
char const* GetExtension(char const* FileName)
{
char const* szTemp;
if ((szTemp = strrchr(FileName, '.')) != NULL)
{ return szTemp; }
return NULL;
}
ADTFile::ADTFile(char* filename): ADT(filename)
{
Adtfilename.append(filename);
AdtFilename.append(filename);
}
bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, StringSet& failedPaths)
{
if (ADT.isEof())
{ return false; }
if (ADT.isEof()) { return false; }
uint32 size;
string xMap;
string yMap;
std::string xMap;
std::string yMap;
Adtfilename.erase(Adtfilename.find(".adt"), 4);
string TempMapNumber;
TempMapNumber = Adtfilename.substr(Adtfilename.length() - 6, 6);
AdtFilename.erase(AdtFilename.find(".adt"), 4);
std::string TempMapNumber;
TempMapNumber = AdtFilename.substr(AdtFilename.length() - 6, 6);
xMap = TempMapNumber.substr(TempMapNumber.find("_") + 1, (TempMapNumber.find_last_of("_") - 1) - (TempMapNumber.find("_")));
yMap = TempMapNumber.substr(TempMapNumber.find_last_of("_") + 1, (TempMapNumber.length()) - (TempMapNumber.find_last_of("_")));
Adtfilename.erase((Adtfilename.length() - xMap.length() - yMap.length() - 2), (xMap.length() + yMap.length() + 2));
string AdtMapNumber = xMap + ' ' + yMap + ' ' + GetPlainName((char*)Adtfilename.c_str());
//printf("Processing map %s...\n", AdtMapNumber.c_str());
//printf("MapNumber = %s\n", TempMapNumber.c_str());
//printf("xMap = %s\n", xMap.c_str());
//printf("yMap = %s\n", yMap.c_str());
AdtFilename.erase((AdtFilename.length() - xMap.length() - yMap.length() - 2), (xMap.length() + yMap.length() + 2));
std::string AdtMapNumber = xMap + ' ' + yMap + ' ' + GetUniformName(AdtFilename);
std::string dirname = std::string(szWorkDirWmo) + "/dir_bin";
FILE* dirfile;
@ -145,17 +90,13 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, StringSet& failed
ADT.read(buf, size);
char* p = buf;
int t = 0;
ModelInstansName = new string[size];
ModelInstansName = new std::string[size];
while (p < buf + size)
{
fixnamen(p, strlen(p));
char* s = GetPlainName(p);
fixname2(s, strlen(s));
string path(p); // Store copy after name fixed
std::string fixedName;
ExtractSingleModel(path, fixedName, failedPaths);
ModelInstansName[t++] = fixedName;
std::string path(p);
std::string uName;
ExtractSingleModel(path, uName, failedPaths);
ModelInstansName[t++] = uName;
p = p + strlen(p) + 1;
}
@ -170,15 +111,13 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, StringSet& failed
ADT.read(buf, size);
char* p = buf;
int q = 0;
WmoInstansName = new string[size];
WmoInstansName = new std::string[size];
while (p < buf + size)
{
string path(p);
char* s = GetPlainName(p);
fixnamen(s, strlen(s));
fixname2(s, strlen(s));
std::string path(p);
WmoInstansName[q++] = GetUniformName(path);
;
p = p + strlen(p) + 1;
WmoInstansName[q++] = s;
}
delete[] buf;
}
@ -193,7 +132,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, StringSet& failed
{
uint32 id;
ADT.read(&id, 4);
ModelInstance inst(ADT, ModelInstansName[id].c_str(), map_num, tileX, tileY, dirfile);
ModelInstance inst(ADT, ModelInstansName[id], map_num, tileX, tileY, dirfile);
}
delete[] ModelInstansName;
}
@ -207,7 +146,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, StringSet& failed
{
uint32 id;
ADT.read(&id, 4);
WMOInstance inst(ADT, WmoInstansName[id].c_str(), map_num, tileX, tileY, dirfile);
WMOInstance inst(ADT, WmoInstansName[id], map_num, tileX, tileY, dirfile);
}
delete[] WmoInstansName;
}

View File

@ -175,57 +175,9 @@ class ADTFile
* @return bool
*/
bool init(uint32 map_num, uint32 tileX, uint32 tileY, StringSet& failedPaths);
//void LoadMapChunks();
//uint32 wmo_count;
/*
const mcell& Getmcell() const
{
return Mcell;
}
*/
private:
//size_t mcnk_offsets[256], mcnk_sizes[256];
MPQFile ADT; /**< TODO */
//mcell Mcell;
string Adtfilename; /**< TODO */
string AdtFilename; /**< TODO */
};
/**
* @brief
*
* @param FileName
* @return const char
*/
const char* GetPlainName(const char* FileName);
/**
* @brief
*
* @param FileName
* @return char
*/
char* GetPlainName(char* FileName);
/**
* @brief
*
* @param FileName
* @return const char
*/
char const* GetExtension(char const* FileName);
/**
* @brief
*
* @param name
* @param len
*/
void fixnamen(char* name, size_t len);
/**
* @brief
*
* @param name
* @param len
*/
void fixname2(char* name, size_t len);
//void fixMapNamen(char *name, size_t len);
#endif

View File

@ -1,135 +0,0 @@
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2015 MaNGOS project <http://getmangos.eu>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "model.h"
#include "dbcfile.h"
#include "adtfile.h"
#include "vmapexport.h"
#include <algorithm>
#include <stdio.h>
bool ExtractSingleModel(std::string& origPath, std::string& fixedName, StringSet& failedPaths)
{
char const* ext = GetExtension(GetPlainName(origPath.c_str()));
// < 3.1.0 ADT MMDX section store filename.mdx filenames for corresponded .m2 file
if (!strcmp(ext, ".mdx"))
{
// replace .mdx -> .m2
origPath.erase(origPath.length() - 2, 2);
origPath.append("2");
}
// >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file
// nothing do
fixedName = GetPlainName(origPath.c_str());
std::string output(szWorkDirWmo); // Stores output filename (possible changed)
output += "/";
output += fixedName;
if (FileExists(output.c_str()))
{ return true; }
Model mdl(origPath); // Possible changed fname
if (!mdl.open(failedPaths))
{ return false; }
return mdl.ConvertToVMAPModel(output.c_str());
}
void ExtractGameobjectModels()
{
printf("\n");
printf("Extracting GameObject models...\n");
DBCFile dbc("DBFilesClient\\GameObjectDisplayInfo.dbc");
if (!dbc.open())
{
printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n");
exit(1);
}
std::string basepath = szWorkDirWmo;
basepath += "/";
std::string path;
StringSet failedPaths;
FILE* model_list = fopen((basepath + "temp_gameobject_models").c_str(), "wb");
for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it)
{
path = it->getString(1);
if (path.length() < 4)
{ continue; }
fixnamen((char*)path.c_str(), path.size());
char* name = GetPlainName((char*)path.c_str());
fixname2(name, strlen(name));
char const* ch_ext = GetExtension(name);
if (!ch_ext)
{ continue; }
//strToLower(ch_ext);
bool result = false;
if (!strcmp(ch_ext, ".wmo"))
{
result = ExtractSingleWmo(path);
}
else if (!strcmp(ch_ext, ".mdl"))
{
// TODO: extract .mdl files, if needed
continue;
}
else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2"))
{
std::string fixedName;
result = ExtractSingleModel(path, fixedName, failedPaths);
}
if (result)
{
uint32 displayId = it->getUInt(0);
uint32 path_length = strlen(name);
fwrite(&displayId, sizeof(uint32), 1, model_list);
fwrite(&path_length, sizeof(uint32), 1, model_list);
fwrite(name, sizeof(char), path_length, model_list);
}
}
fclose(model_list);
if (!failedPaths.empty())
{
printf("Warning: Some models could not be extracted, see below\n");
for (StringSet::const_iterator itr = failedPaths.begin(); itr != failedPaths.end(); ++itr)
{ printf("Could not find file of model %s\n", itr->c_str()); }
printf("A few of these warnings are expected to happen, so be not alarmed!\n");
}
printf("Done!\n");
}

View File

@ -22,13 +22,27 @@
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include <ml/mpq.h>
#include "vmapexport.h"
#include "model.h"
#include "wmo.h"
#include <cassert>
#include <algorithm>
#include <cstdio>
#include <ml/mpq.h>
#include "model.h"
#include "wmo.h"
#include "dbcfile.h"
using namespace std;
Vec3D fixCoordSystem(Vec3D v)
{
return Vec3D(v.x, v.z, -v.y);
}
Vec3D fixCoordSystem2(Vec3D v)
{
return Vec3D(v.x, v.z, v.y);
}
Model::Model(std::string& filename) : filename(filename), vertices(0), indices(0)
{
@ -77,37 +91,38 @@ bool Model::open(StringSet& failedPaths)
return true;
}
bool Model::ConvertToVMAPModel(const char* outfilename)
bool Model::ConvertToVMAPModel(std::string& outfilename)
{
int N[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
FILE* output = fopen(outfilename, "wb");
FILE* output = fopen(outfilename.c_str(), "wb");
if (!output)
{
printf("Can't create the output file '%s'\n", outfilename);
printf("Can't create the output file '%s'\n", outfilename.c_str());
return false;
}
fwrite(szRawVMAPMagic, 8, 1, output);
std::fwrite(szRawVMAPMagic, 8, 1, output);
uint32 nVertices = 0;
nVertices = header.nBoundingVertices;
fwrite(&nVertices, sizeof(int), 1, output);
std::fwrite(&nVertices, sizeof(int), 1, output);
uint32 nofgroups = 1;
fwrite(&nofgroups, sizeof(uint32), 1, output);
fwrite(N, 4 * 3, 1, output); // rootwmoid, flags, groupid
fwrite(N, sizeof(float), 3 * 2, output); //bbox, only needed for WMO currently
fwrite(N, 4, 1, output); // liquidflags
fwrite("GRP ", 4, 1, output);
std::fwrite(&nofgroups, sizeof(uint32), 1, output);
std::fwrite(N, 4 * 3, 1, output); // rootwmoid, flags, groupid
std::fwrite(N, sizeof(float), 3 * 2, output); //bbox, only needed for WMO currently
std::fwrite(N, 4, 1, output); // liquidflags
std::fwrite("GRP ", 4, 1, output);
uint32 branches = 1;
int wsize;
wsize = sizeof(branches) + sizeof(uint32) * branches;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&branches, sizeof(branches), 1, output);
std::fwrite(&wsize, sizeof(int), 1, output);
std::fwrite(&branches, sizeof(branches), 1, output);
uint32 nIndexes = (uint32) nIndices;
fwrite(&nIndexes, sizeof(uint32), 1, output);
fwrite("INDX", 4, 1, output);
std::fwrite(&nIndexes, sizeof(uint32), 1, output);
std::fwrite("INDX", 4, 1, output);
wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&nIndexes, sizeof(uint32), 1, output);
std::fwrite(&wsize, sizeof(int), 1, output);
std::fwrite(&nIndexes, sizeof(uint32), 1, output);
if (nIndexes > 0)
{
for (uint32 i = 0; i < nIndices; ++i)
@ -120,12 +135,12 @@ bool Model::ConvertToVMAPModel(const char* outfilename)
indices[i+1] = tmp;
}
}
fwrite(indices, sizeof(unsigned short), nIndexes, output);
std::fwrite(indices, sizeof(unsigned short), nIndexes, output);
}
fwrite("VERT", 4, 1, output);
std::fwrite("VERT", 4, 1, output);
wsize = sizeof(int) + sizeof(float) * 3 * nVertices;
fwrite(&wsize, sizeof(int), 1, output);
fwrite(&nVertices, sizeof(int), 1, output);
std::fwrite(&wsize, sizeof(int), 1, output);
std::fwrite(&nVertices, sizeof(int), 1, output);
if (nVertices > 0)
{
for (uint32 vpos = 0; vpos < nVertices; ++vpos)
@ -134,7 +149,7 @@ bool Model::ConvertToVMAPModel(const char* outfilename)
vertices[vpos].y = -vertices[vpos].z;
vertices[vpos].z = tmp;
}
fwrite(vertices, sizeof(float) * 3, nVertices, output);
std::fwrite(vertices, sizeof(float) * 3, nVertices, output);
}
fclose(output);
@ -143,17 +158,8 @@ bool Model::ConvertToVMAPModel(const char* outfilename)
}
Vec3D fixCoordSystem(Vec3D v)
{
return Vec3D(v.x, v.z, -v.y);
}
Vec3D fixCoordSystem2(Vec3D v)
{
return Vec3D(v.x, v.z, v.y);
}
ModelInstance::ModelInstance(MPQFile& f, const char* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
ModelInstance::ModelInstance(MPQFile& f, string& ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
{
float ff[3];
f.read(&id, 4);
@ -170,7 +176,7 @@ ModelInstance::ModelInstance(MPQFile& f, const char* ModelInstName, uint32 mapID
sc = scale / 1024.0f;
char tempname[512];
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName);
sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName.c_str());
FILE* input;
input = fopen(tempname, "r+b");
@ -192,32 +198,115 @@ ModelInstance::ModelInstance(MPQFile& f, const char* ModelInstName, uint32 mapID
uint32 flags = MOD_M2;
if (tileX == 65 && tileY == 65) { flags |= MOD_WORLDSPAWN; }
//write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, name
fwrite(&mapID, sizeof(uint32), 1, pDirfile);
fwrite(&tileX, sizeof(uint32), 1, pDirfile);
fwrite(&tileY, sizeof(uint32), 1, pDirfile);
fwrite(&flags, sizeof(uint32), 1, pDirfile);
fwrite(&adtId, sizeof(uint16), 1, pDirfile);
fwrite(&id, sizeof(uint32), 1, pDirfile);
fwrite(&pos, sizeof(float), 3, pDirfile);
fwrite(&rot, sizeof(float), 3, pDirfile);
fwrite(&sc, sizeof(float), 1, pDirfile);
uint32 nlen = strlen(ModelInstName);
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
fwrite(ModelInstName, sizeof(char), nlen, pDirfile);
std::fwrite(&mapID, sizeof(uint32), 1, pDirfile);
std::fwrite(&tileX, sizeof(uint32), 1, pDirfile);
std::fwrite(&tileY, sizeof(uint32), 1, pDirfile);
std::fwrite(&flags, sizeof(uint32), 1, pDirfile);
std::fwrite(&adtId, sizeof(uint16), 1, pDirfile);
std::fwrite(&id, sizeof(uint32), 1, pDirfile);
std::fwrite(&pos, sizeof(float), 3, pDirfile);
std::fwrite(&rot, sizeof(float), 3, pDirfile);
std::fwrite(&sc, sizeof(float), 1, pDirfile);
uint32 nlen = ModelInstName.length();
std::fwrite(&nlen, sizeof(uint32), 1, pDirfile);
std::fwrite(ModelInstName.c_str(), sizeof(char), nlen, pDirfile);
/* int realx1 = (int) ((float) pos.x / 533.333333f);
int realy1 = (int) ((float) pos.z / 533.333333f);
int realx2 = (int) ((float) pos.x / 533.333333f);
int realy2 = (int) ((float) pos.z / 533.333333f);
fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n",
MapName,
ModelInstName,
(float) pos.x, (float) pos.y, (float) pos.z,
(float) rot.x, (float) rot.y, (float) rot.z,
sc,
nVertices,
realx1, realy1,
realx2, realy2
); */
}
bool ExtractSingleModel(std::string& origPath, std::string& fixedName, StringSet& failedPaths)
{
string ext = GetExtension(origPath);
// < 3.1.0 ADT MMDX section store filename.mdx filenames for corresponded .m2 file
if (ext == "mdx")
{
// replace .mdx -> .m2
origPath.erase(origPath.length() - 2, 2);
origPath.append("2");
}
// >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file
// nothing do
fixedName = GetUniformName(origPath);
std::string output(szWorkDirWmo); // Stores output filename
output += "/";
output += fixedName;
if (FileExists(output.c_str()))
{ return true; }
Model mdl(origPath); // Possible changed fname
if (!mdl.open(failedPaths))
{ return false; }
return mdl.ConvertToVMAPModel(output);
}
void ExtractGameobjectModels()
{
printf("\n");
printf("Extracting GameObject models...\n");
DBCFile dbc("DBFilesClient\\GameObjectDisplayInfo.dbc");
if (!dbc.open())
{
printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n");
exit(1);
}
std::string basepath = szWorkDirWmo;
basepath += "/";
std::string path;
StringSet failedPaths;
FILE* model_list = fopen((basepath + "temp_gameobject_models").c_str(), "wb");
for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it)
{
path = it->getString(1);
if (path.length() < 4)
{ continue; }
string name;
string ch_ext = GetExtension(path);
if (ch_ext.empty())
{ continue; }
bool result = false;
if (ch_ext == "wmo")
{
result = ExtractSingleWmo(path);
}
else if (ch_ext == "mdl")
{
// TODO: extract .mdl files, if needed
continue;
}
else
{
result = ExtractSingleModel(path, name, failedPaths);
}
if (result)
{
uint32 displayId = it->getUInt(0);
uint32 path_length = name.length();
std::fwrite(&displayId, sizeof(uint32), 1, model_list);
std::fwrite(&path_length, sizeof(uint32), 1, model_list);
std::fwrite(name.c_str(), sizeof(char), path_length, model_list);
}
}
fclose(model_list);
if (!failedPaths.empty())
{
printf("Warning: Some models could not be extracted, see below\n");
for (StringSet::const_iterator itr = failedPaths.begin(); itr != failedPaths.end(); ++itr)
{ printf("Could not find file of model %s\n", itr->c_str()); }
printf("A few of these warnings are expected to happen, so be not alarmed!\n");
}
printf("Done!\n");
}

View File

@ -68,7 +68,7 @@ class Model
* @param outfilename
* @return bool
*/
bool ConvertToVMAPModel(const char* outfilename);
bool ConvertToVMAPModel(std::string& outfilename);
bool ok; /**< TODO */
@ -97,7 +97,6 @@ class Model
indices = NULL;
}
std::string filename; /**< TODO */
char outfilename; /**< TODO */
};
/**
@ -131,8 +130,24 @@ class ModelInstance
* @param tileY
* @param pDirfile
*/
ModelInstance(MPQFile& f, const char* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
ModelInstance(MPQFile& f, std::string& ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
};
/**
* @brief
*
* @param origPath original path of the model, cleaned with fixnamen and fixname2
* @param fixedName will store the translated name (if changed)
* @param failedPaths Set to collect errors
* @return bool
*/
bool ExtractSingleModel(std::string& origPath, std::string& fixedName, StringSet& failedPaths);
/**
* @brief
*
*/
void ExtractGameobjectModels();
#endif

View File

@ -27,6 +27,8 @@
#include <vector>
#include <list>
#include <errno.h>
#include <sstream>
#include <iomanip>
#if defined WIN32
#include <Windows.h>
@ -53,12 +55,12 @@
#include <ml/mpq.h>
#include "vmapexport.h"
#include "Auth/md5.h"
//------------------------------------------------------------------------------
// Defines
#define MPQ_BLOCK_SIZE 0x1000
//-----------------------------------------------------------------------------
extern ArchiveSet gOpenArchives;
@ -87,7 +89,7 @@ const char* szRawVMAPMagic = "VMAPz05";
bool FileExists(const char* file)
{
if (FILE* n = fopen(file, "rb"))
if (FILE* n = std::fopen(file, "rb"))
{
fclose(n);
return true;
@ -95,13 +97,58 @@ bool FileExists(const char* file)
return false;
}
void strToLower(char* str)
void compute_md5(const char* value, char* result)
{
while (*str)
md5_byte_t digest[16];
md5_state_t ctx;
md5_init(&ctx);
md5_append(&ctx, (const unsigned char*)value, strlen(value));
md5_finish(&ctx, digest);
for(int i=0;i<16;i++)
sprintf(result+2*i,"%02x",digest[i]);
result[32]='\0';
}
std::string GetUniformName(std::string& path)
{
std::transform(path.begin(),path.end(),path.begin(),::tolower);
string tempPath;
string file;
char digest[33];
std::size_t found = path.find_last_of("/\\");
if (found != string::npos)
{
*str = tolower(*str);
++str;
file = path.substr(found+1);
tempPath = path.substr(0,found);
}
else { file = tempPath = path; }
if (tempPath == "<empty>") //GameObjectDisplayInfo, OnyxiasLair
tempPath.assign("world\\wmo\\dungeon\\kl_onyxiaslair");
if(!tempPath.empty())
compute_md5(tempPath.c_str(),digest);
else
compute_md5("\\",digest);
string result;
result = result.assign(digest) + "-" + file;
return result;
}
std::string GetExtension(std::string& path)
{
string ext;
size_t foundExt = path.find_last_of(".");
if (foundExt != std::string::npos) { ext=path.substr(foundExt+1);}
else {ext.clear();}
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return ext;
}
// copied from contrib/extractor/System.cpp
@ -131,7 +178,7 @@ void ReadLiquidTypeTableDBC()
bool ExtractWmo()
{
bool success = true;
for (ArchiveSet::const_iterator ar_itr = gOpenArchives.begin(); ar_itr != gOpenArchives.end() && success; ++ar_itr)
{
vector<string> filelist;
@ -139,8 +186,7 @@ bool ExtractWmo()
(*ar_itr)->GetFileListTo(filelist);
for (vector<string>::iterator fname = filelist.begin(); fname != filelist.end() && success; ++fname)
{
if (fname->find(".wmo") != string::npos)
{ success = ExtractSingleWmo(*fname); }
if (fname->find(".wmo") != string::npos) { success = ExtractSingleWmo(*fname);}
}
}
@ -155,16 +201,16 @@ bool ExtractSingleWmo(std::string& fname)
// Copy files from archive
char szLocalFile[1024];
const char* plain_name = GetPlainName(fname.c_str());
sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name);
fixnamen(szLocalFile, strlen(szLocalFile));
string plain_name = GetUniformName(fname);
sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name.c_str());
if (FileExists(szLocalFile))
{ return true; }
int p = 0;
//Select root wmo files
const char* rchr = strrchr(plain_name, '_');
const char* rchr = strrchr(plain_name.c_str(), '_');
if (rchr != NULL)
{
char cpy[4];
@ -188,15 +234,16 @@ bool ExtractSingleWmo(std::string& fname)
printf("Couldn't open RootWmo!!!\n");
return true;
}
FILE* output = fopen(szLocalFile, "wb");
if (!output)
{
printf("couldn't open %s for writing!\n", szLocalFile);
return false;
}
froot.ConvertToVMAPRootWmo(output);
int Wmo_nVertices = 0;
//printf("root has %d groups\n", froot->nGroups);
if (froot.nGroups != 0)
{
for (uint32 i = 0; i < froot.nGroups; ++i)
@ -206,13 +253,13 @@ bool ExtractSingleWmo(std::string& fname)
temp[fname.length() - 4] = 0;
char groupFileName[1024];
sprintf(groupFileName, "%s_%03d.wmo", temp, i);
//printf("Trying to open groupfile %s\n",groupFileName);
string s = groupFileName;
string s(groupFileName);
WMOGroup fgroup(s);
if (!fgroup.open())
{
printf("Could not open all Group file for: %s\n", plain_name);
printf("Could not open all Group file for: %s\n", plain_name.c_str());
file_ok = false;
break;
}

View File

@ -49,41 +49,27 @@ extern const char* szWorkDirWmo; /**< TODO */
extern const char* szRawVMAPMagic; /**< vmap magic string for extracted raw vmap data */
/**
* @brief
* @brief Test if the specified file exists in the building directory
*
* @param file
* @return bool
*/
bool FileExists(const char* file);
/**
* @brief
*
* @param str
*/
void strToLower(char* str);
/**
* @brief
* @brief Get "uniform" name for a path (a uniform name has the format <md5hash>-<filename>.<ext>)
*
* @param fname
* @return bool
* @param path
* @return string
*/
bool ExtractSingleWmo(std::string& fname);
std::string GetUniformName(std::string& path);
/**
* @brief
* @brief Get extension for a file
*
* @param origPath original path of the model, cleaned with fixnamen and fixname2
* @param fixedName will store the translated name (if changed)
* @param failedPaths Set to collect errors
* @return bool
* @param file
* @return extension, if found, or std::string::npos if not
*/
bool ExtractSingleModel(std::string& origPath, std::string& fixedName, StringSet& failedPaths);
/**
* @brief
*
*/
void ExtractGameobjectModels();
std::string GetExtension(std::string& file);
#endif

View File

@ -27,15 +27,6 @@
#include "adtfile.h"
#include <cstdio>
char* wdtGetPlainName(char* FileName)
{
char* szTemp;
if ((szTemp = strrchr(FileName, '\\')) != NULL)
{ FileName = szTemp + 1; }
return FileName;
}
WDTFile::WDTFile(char* file_name, char* file_name1): WDT(file_name)
{
filename.append(file_name1, strlen(file_name1));
@ -87,10 +78,8 @@ bool WDTFile::init(char* map_id, unsigned int mapID)
while (p < buf + size)
{
string path(p);
char* s = wdtGetPlainName(p);
fixnamen(s, strlen(s));
gWmoInstansName[q++] = GetUniformName(path);
p = p + strlen(p) + 1;
gWmoInstansName[q++] = s;
}
delete[] buf;
}
@ -110,7 +99,7 @@ bool WDTFile::init(char* map_id, unsigned int mapID)
{
int id;
WDT.read(&id, 4);
WMOInstance inst(WDT, gWmoInstansName[id].c_str(), mapID, 65, 65, dirfile);
WMOInstance inst(WDT, gWmoInstansName[id], mapID, 65, 65, dirfile);
}
delete[] gWmoInstansName;
}

View File

@ -490,7 +490,8 @@ WMOGroup::~WMOGroup()
delete [] LiquBytes;
}
WMOInstance::WMOInstance(MPQFile& f, const char* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
//WmoInstName is in the form MD5/name.wmo
WMOInstance::WMOInstance(MPQFile& f, std::string& WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile)
{
pos = Vec3D(0, 0, 0);
@ -513,7 +514,7 @@ WMOInstance::WMOInstance(MPQFile& f, const char* WmoInstName, uint32 mapID, uint
//-----------add_in _dir_file----------------
char tempname[512];
sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName);
sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName.c_str());
FILE* input;
input = fopen(tempname, "r+b");
@ -558,19 +559,8 @@ WMOInstance::WMOInstance(MPQFile& f, const char* WmoInstName, uint32 mapID, uint
fwrite(&scale, sizeof(float), 1, pDirfile);
fwrite(&pos2, sizeof(float), 3, pDirfile);
fwrite(&pos3, sizeof(float), 3, pDirfile);
uint32 nlen = strlen(WmoInstName);
uint32 nlen = WmoInstName.length();
fwrite(&nlen, sizeof(uint32), 1, pDirfile);
fwrite(WmoInstName, sizeof(char), nlen, pDirfile);
fwrite(WmoInstName.c_str(), sizeof(char), nlen, pDirfile);
/* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n",
MapName,
WmoInstName,
(float) x, (float) pos.y, (float) z,
(float) rot.x, (float) rot.y, (float) rot.z,
nVertices,
realx1, realy1,
realx2, realy2
); */
// fclose(dirfile);
}

View File

@ -43,7 +43,6 @@
#define WMO_MATERIAL_WALL_SURFACE 0x40
class WMOInstance;
class WMOManager;
class MPQFile;
/**
@ -93,7 +92,6 @@ class WMORoot
bool ConvertToVMAPRootWmo(FILE* output);
private:
std::string filename; /**< TODO */
char outfilename; /**< TODO */
};
/**
@ -182,7 +180,6 @@ class WMOGroup
private:
std::string filename; /**< TODO */
char outfilename; /**< TODO */
};
/**
@ -212,7 +209,7 @@ class WMOInstance
* @param tileY
* @param pDirfile
*/
WMOInstance(MPQFile& f, const char* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
WMOInstance(MPQFile& f, std::string& WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile);
/**
* @brief
@ -221,4 +218,13 @@ class WMOInstance
static void reset();
};
/**
* @brief
*
* @param fname
* @return bool
*/
bool ExtractSingleWmo(std::string& fname);
#endif