TrinityCore
adtfile.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "vmapexport.h"
19#include "adtfile.h"
20#include "StringFormat.h"
21#include <cstdio>
22#include "Errors.h"
23
24char const* GetPlainName(char const* FileName)
25{
26 const char * szTemp;
27
28 if((szTemp = strrchr(FileName, '\\')) != nullptr)
29 FileName = szTemp + 1;
30 return FileName;
31}
32
33char* GetPlainName(char* FileName)
34{
35 char * szTemp;
36
37 if((szTemp = strrchr(FileName, '\\')) != nullptr)
38 FileName = szTemp + 1;
39 return FileName;
40}
41
42void FixNameCase(char* name, size_t len)
43{
44 char* ptr = name + len - 1;
45
46 //extension in lowercase
47 for (; *ptr != '.'; --ptr)
48 *ptr |= 0x20;
49
50 for (; ptr >= name; --ptr)
51 {
52 if (ptr > name && *ptr >= 'A' && *ptr <= 'Z' && isalpha(*(ptr - 1)))
53 *ptr |= 0x20;
54 else if ((ptr == name || !isalpha(*(ptr - 1))) && *ptr >= 'a' && *ptr <= 'z')
55 *ptr &= ~0x20;
56 }
57}
58
59void FixNameSpaces(char* name, size_t len)
60{
61 if (len < 3)
62 return;
63
64 for (size_t i = 0; i < len - 3; i++)
65 if (name[i] == ' ')
66 name[i] = '_';
67}
68
69void NormalizeFileName(char* name, size_t len)
70{
71 if (len >= 4 && !memcmp(name, "FILE", 4)) // name is FileDataId formatted, do not normalize
72 return;
73
74 FixNameCase(name, len);
75 FixNameSpaces(name, len);
76}
77
78char* GetExtension(char* FileName)
79{
80 if (char* szTemp = strrchr(FileName, '.'))
81 return szTemp;
82 return nullptr;
83}
84
85extern std::shared_ptr<CASC::Storage> CascStorage;
86
87ADTFile::ADTFile(std::string const& filename, bool cache) : _file(CascStorage, filename.c_str(), false)
88{
89 cacheable = cache;
90 dirfileCache = nullptr;
91}
92
93ADTFile::ADTFile(uint32 fileDataId, std::string const& description, bool cache) : _file(CascStorage, fileDataId, description, false)
94{
95 cacheable = cache;
96 dirfileCache = nullptr;
97}
98
99bool ADTFile::init(uint32 map_num, uint32 originalMapId)
100{
101 if (dirfileCache)
102 return initFromCache(map_num, originalMapId);
103
104 if (_file.isEof())
105 return false;
106
107 uint32 size;
108 std::string dirname = std::string(szWorkDirWmo) + "/dir_bin";
109 FILE* dirfile = fopen(dirname.c_str(), "ab");
110 if(!dirfile)
111 {
112 printf("Can't open dirfile!'%s'\n", dirname.c_str());
113 return false;
114 }
115
116 if (cacheable)
117 dirfileCache = new std::vector<ADTOutputCache>();
118
119 while (!_file.isEof())
120 {
121 char fourcc[5];
122 _file.read(&fourcc,4);
123 _file.read(&size, 4);
124 flipcc(fourcc);
125 fourcc[4] = 0;
126
127 size_t nextpos = _file.getPos() + size;
128
129 if (!strcmp(fourcc,"MMDX"))
130 {
131 if (size)
132 {
133 char* buf = new char[size];
134 _file.read(buf, size);
135 char* p = buf;
136 while (p < buf + size)
137 {
138 std::string path(p);
139
140 char* s = GetPlainName(p);
141 NormalizeFileName(s, strlen(s));
142
143 ModelInstanceNames.emplace_back(s);
144
145 ExtractSingleModel(path);
146
147 p += strlen(p) + 1;
148 }
149 delete[] buf;
150 }
151 }
152 else if (!strcmp(fourcc,"MWMO"))
153 {
154 if (size)
155 {
156 char* buf = new char[size];
157 _file.read(buf, size);
158 char* p = buf;
159 while (p < buf + size)
160 {
161 std::string path(p);
162
163 char* s = GetPlainName(p);
164 NormalizeFileName(s, strlen(s));
165
166 WmoInstanceNames.emplace_back(s);
167
168 ExtractSingleWmo(path);
169
170 p += strlen(p) + 1;
171 }
172 delete[] buf;
173 }
174 }
175 //======================
176 else if (!strcmp(fourcc, "MDDF"))
177 {
178 if (size)
179 {
180 uint32 doodadCount = size / sizeof(ADT::MDDF);
181 for (uint32 i = 0; i < doodadCount; ++i)
182 {
183 ADT::MDDF doodadDef;
184 _file.read(&doodadDef, sizeof(ADT::MDDF));
185 if (!(doodadDef.Flags & 0x40))
186 {
187 Doodad::Extract(doodadDef, ModelInstanceNames[doodadDef.Id].c_str(), map_num, originalMapId, dirfile, dirfileCache);
188 }
189 else
190 {
191 std::string fileName = Trinity::StringFormat("FILE{:08X}.xxx", doodadDef.Id);
192 ExtractSingleModel(fileName);
193 Doodad::Extract(doodadDef, fileName.c_str(), map_num, originalMapId, dirfile, dirfileCache);
194 }
195 }
196
197 ModelInstanceNames.clear();
198 }
199 }
200 else if (!strcmp(fourcc,"MODF"))
201 {
202 if (size)
203 {
204 uint32 mapObjectCount = size / sizeof(ADT::MODF);
205 for (uint32 i = 0; i < mapObjectCount; ++i)
206 {
207 ADT::MODF mapObjDef;
208 _file.read(&mapObjDef, sizeof(ADT::MODF));
209 if (!(mapObjDef.Flags & 0x8))
210 {
211 MapObject::Extract(mapObjDef, WmoInstanceNames[mapObjDef.Id].c_str(), false, map_num, originalMapId, dirfile, dirfileCache);
212 Doodad::ExtractSet(WmoDoodads[WmoInstanceNames[mapObjDef.Id]], mapObjDef, false, map_num, originalMapId, dirfile, dirfileCache);
213 }
214 else
215 {
216 std::string fileName = Trinity::StringFormat("FILE{:08X}.xxx", mapObjDef.Id);
217 ExtractSingleWmo(fileName);
218 MapObject::Extract(mapObjDef, fileName.c_str(), false, map_num, originalMapId, dirfile, dirfileCache);
219 Doodad::ExtractSet(WmoDoodads[fileName], mapObjDef, false, map_num, originalMapId, dirfile, dirfileCache);
220 }
221 }
222
223 WmoInstanceNames.clear();
224 }
225 }
226
227 //======================
228 _file.seek(nextpos);
229 }
230
231 _file.close();
232 fclose(dirfile);
233 return true;
234}
235
236bool ADTFile::initFromCache(uint32 map_num, uint32 originalMapId)
237{
238 if (dirfileCache->empty())
239 return true;
240
241 std::string dirname = std::string(szWorkDirWmo) + "/dir_bin";
242 FILE* dirfile = fopen(dirname.c_str(), "ab");
243 if (!dirfile)
244 {
245 printf("Can't open dirfile!'%s'\n", dirname.c_str());
246 return false;
247 }
248
249 for (ADTOutputCache const& cached : *dirfileCache)
250 {
251 fwrite(&map_num, sizeof(uint32), 1, dirfile);
252 uint8 flags = cached.Flags;
253 if (map_num != originalMapId)
255 fwrite(&flags, sizeof(uint8), 1, dirfile);
256 fwrite(cached.Data.data(), cached.Data.size(), 1, dirfile);
257 }
258
259 fclose(dirfile);
260 return true;
261}
262
264{
265 _file.close();
266 delete dirfileCache;
267}
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
uint16 flags
Definition: DisableMgr.cpp:49
std::shared_ptr< CASC::Storage > CascStorage
Definition: System.cpp:49
char const * GetPlainName(char const *FileName)
Definition: adtfile.cpp:24
void FixNameCase(char *name, size_t len)
Definition: adtfile.cpp:42
char * GetExtension(char *FileName)
Definition: adtfile.cpp:78
void FixNameSpaces(char *name, size_t len)
Definition: adtfile.cpp:59
void NormalizeFileName(char *name, size_t len)
Definition: adtfile.cpp:69
void flipcc(char *fcc)
Definition: cascfile.h:58
ADTFile(std::string const &filename, bool cache)
Definition: adtfile.cpp:87
bool cacheable
Definition: adtfile.h:63
std::vector< std::string > ModelInstanceNames
Definition: adtfile.h:70
CASCFile _file
Definition: adtfile.h:62
std::vector< ADTOutputCache > * dirfileCache
Definition: adtfile.h:64
std::vector< std::string > WmoInstanceNames
Definition: adtfile.h:69
~ADTFile()
Definition: adtfile.cpp:263
bool init(uint32 map_num, uint32 originalMapId)
Definition: adtfile.cpp:99
bool initFromCache(uint32 map_num, uint32 originalMapId)
Definition: adtfile.cpp:236
bool isEof()
Definition: cascfile.h:52
void seek(int offset)
Definition: cascfile.cpp:99
size_t read(void *dest, size_t bytes)
Definition: cascfile.cpp:80
size_t getPos()
Definition: cascfile.h:49
void close()
Definition: cascfile.cpp:111
bool ExtractSingleModel(std::string &fname)
void Extract(ADT::MDDF const &doodadDef, char const *ModelInstName, uint32 mapID, uint32 originalMapId, FILE *pDirfile, std::vector< ADTOutputCache > *dirfileCache)
Definition: model.cpp:160
void ExtractSet(WMODoodadData const &doodadData, ADT::MODF const &wmo, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, FILE *pDirfile, std::vector< ADTOutputCache > *dirfileCache)
Definition: model.cpp:226
void Extract(ADT::MODF const &mapObjDef, char const *WmoInstName, bool isGlobalWmo, uint32 mapID, uint32 originalMapId, FILE *pDirfile, std::vector< ADTOutputCache > *dirfileCache)
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
constexpr std::size_t size()
Definition: UpdateField.h:796
uint16 Flags
Definition: adtfile.h:35
uint32 Id
Definition: adtfile.h:30
uint16 Flags
Definition: adtfile.h:45
uint32 Id
Definition: adtfile.h:40
std::unordered_map< std::string, WMODoodadData > WmoDoodads
Definition: vmapexport.cpp:70
char const * szWorkDirWmo
Definition: vmapexport.cpp:74
bool ExtractSingleWmo(std::string &fname)
Definition: vmapexport.cpp:188
@ MOD_PARENT_SPAWN
Definition: vmapexport.h:29