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:
parent
7cbeac65d4
commit
25e241b4b8
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
}
|
@ -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");
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user