TrinityCore
Loading...
Searching...
No Matches
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 "adtfile.h"
19#include "Common.h"
20#include "Memory.h"
21#include "StringFormat.h"
22#include "Util.h"
23#include "model.h"
24#include "vmapexport.h"
25#include "wmo.h"
26#include <algorithm>
27#include <cstdio>
28
29std::string_view GetPlainName(std::string_view fileName)
30{
31 std::size_t lastSeparatorPos = fileName.find_last_of("\\/"sv);
32
33 if (lastSeparatorPos != std::string_view::npos)
34 fileName.remove_prefix(lastSeparatorPos + 1);
35
36 return fileName;
37}
38
39void NormalizeFileName(std::string& name)
40{
41 if (name.starts_with("FILE"sv)) // name is FileDataId formatted, do not normalize
42 return;
43
44 auto ptr = name.begin() + (name.length() - 1);
45
46 //extension in lowercase
47 for (; *ptr != '.' && ptr > name.begin(); --ptr)
48 if (*ptr >= 'A' && *ptr <= 'Z')
49 *ptr |= 0x20;
50
51 for (; ptr > name.begin(); --ptr)
52 {
53 if (ptr > name.begin() && *ptr >= 'A' && *ptr <= 'Z' && isalpha(*(ptr - 1)))
54 *ptr |= 0x20;
55 else if ((ptr == name.begin() || !isalpha(*(ptr - 1))) && *ptr >= 'a' && *ptr <= 'z')
56 *ptr &= ~0x20;
57 else if (*ptr == ' ')
58 *ptr = '_';
59 }
60}
61
62extern std::shared_ptr<CASC::Storage> CascStorage;
63
64ADTFile::ADTFile(std::string const& filename, bool cache) : _file(CascStorage, filename.c_str(), false)
65{
66 cacheable = cache;
67 dirfileCache = nullptr;
68}
69
70ADTFile::ADTFile(uint32 fileDataId, std::string const& description, bool cache) : _file(CascStorage, fileDataId, description, false)
71{
72 cacheable = cache;
73 dirfileCache = nullptr;
74}
75
76bool ADTFile::init(uint32 map_num, uint32 originalMapId)
77{
78 if (dirfileCache)
79 return initFromCache(map_num, originalMapId);
80
81 if (_file.isEof())
82 return false;
83
84 uint32 size;
85 std::string dirname = Trinity::StringFormat("{}/dir_bin/{:04}", szWorkDirWmo, map_num);
86 auto dirfile = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(dirname.c_str(), "ab"));
87 if(!dirfile)
88 {
89 printf("Can't open dirfile!'%s'\n", dirname.c_str());
90 return false;
91 }
92
93 if (cacheable)
94 dirfileCache = new std::vector<ADTOutputCache>();
95
96 while (!_file.isEof())
97 {
98 char fourcc[4];
99 _file.read(&fourcc,4);
100 _file.read(&size, 4);
101 std::ranges::reverse(fourcc);
102
103 size_t nextpos = _file.getPos() + size;
104
105 if (!memcmp(fourcc, "MMDX", 4))
106 {
107 if (size)
108 {
109 char* p = _file.getPointer();
110 _file.seekRelative(size);
111 char* end = _file.getPointer();
112 while (p < end)
113 {
114 std::size_t length = std::ranges::distance(p, CStringSentinel.Checked(end));
115 ModelInstanceNames.emplace_back(p, length);
116
117 p += length + 1;
118 }
119 }
120 }
121 else if (!memcmp(fourcc, "MWMO", 4))
122 {
123 if (size)
124 {
125 char* p = _file.getPointer();
126 _file.seekRelative(size);
127 char* end = _file.getPointer();
128 while (p < end)
129 {
130 std::size_t length = std::ranges::distance(p, CStringSentinel.Checked(end));
131 WmoInstanceNames.emplace_back(p, length);
132
133 p += length + 1;
134 }
135 }
136 }
137 //======================
138 else if (!memcmp(fourcc, "MDDF", 4))
139 {
140 if (size)
141 {
142 uint32 doodadCount = size / sizeof(ADT::MDDF);
143 for (uint32 i = 0; i < doodadCount; ++i)
144 {
145 ADT::MDDF doodadDef;
146 _file.read(&doodadDef, sizeof(ADT::MDDF));
147
148 std::string fileName;
149 if (doodadDef.Flags & 0x40)
150 fileName = Trinity::StringFormat("FILE{:08X}.xxx", doodadDef.Id);
151 else
152 fileName = ModelInstanceNames[doodadDef.Id];
153
154 if (ExtractSingleModel(fileName))
155 Doodad::Extract(doodadDef, fileName.c_str(), map_num, originalMapId, dirfile.get(), dirfileCache);
156 }
157
158 ModelInstanceNames.clear();
159 }
160 }
161 else if (!memcmp(fourcc, "MODF", 4))
162 {
163 if (size)
164 {
165 uint32 mapObjectCount = size / sizeof(ADT::MODF);
166 for (uint32 i = 0; i < mapObjectCount; ++i)
167 {
168 ADT::MODF mapObjDef;
169 _file.read(&mapObjDef, sizeof(ADT::MODF));
170
171 std::string fileName;
172 if (mapObjDef.Flags & 0x8)
173 fileName = Trinity::StringFormat("FILE{:08X}.xxx", mapObjDef.Id);
174 else
175 fileName = WmoInstanceNames[mapObjDef.Id];
176
177 if (ExtractedModelData const* extracted = ExtractSingleWmo(fileName))
178 {
179 if (extracted->HasCollision())
180 MapObject::Extract(mapObjDef, fileName.c_str(), false, map_num, originalMapId, dirfile.get(), dirfileCache);
181
182 if (extracted->Doodads)
183 Doodad::ExtractSet(*extracted->Doodads, mapObjDef, false, map_num, originalMapId, dirfile.get(), dirfileCache);
184 }
185 }
186
187 WmoInstanceNames.clear();
188 }
189 }
190
191 //======================
192 _file.seek(nextpos);
193 }
194
195 _file.close();
196 return true;
197}
198
199bool ADTFile::initFromCache(uint32 map_num, uint32 originalMapId)
200{
201 if (dirfileCache->empty())
202 return true;
203
204 std::string dirname = Trinity::StringFormat("{}/dir_bin/{:04}", szWorkDirWmo, map_num);
205 auto dirfile = Trinity::make_unique_ptr_with_deleter<&::fclose>(fopen(dirname.c_str(), "ab"));
206 if (!dirfile)
207 {
208 printf("Can't open dirfile!'%s'\n", dirname.c_str());
209 return false;
210 }
211
212 for (ADTOutputCache const& cached : *dirfileCache)
213 {
214 uint8 flags = cached.Flags;
215 if (map_num != originalMapId)
217 fwrite(&flags, sizeof(uint8), 1, dirfile.get());
218 fwrite(cached.Data.data(), cached.Data.size(), 1, dirfile.get());
219 }
220
221 return true;
222}
223
225{
226 _file.close();
227 delete dirfileCache;
228}
uint8_t uint8
Definition Define.h:156
uint32_t uint32
Definition Define.h:154
uint16 flags
struct CStringSentinel_T CStringSentinel
std::shared_ptr< CASC::Storage > CascStorage
Definition System.cpp:51
void NormalizeFileName(std::string &name)
Definition adtfile.cpp:39
std::string_view GetPlainName(std::string_view fileName)
Definition adtfile.cpp:29
ADTFile(std::string const &filename, bool cache)
Definition adtfile.cpp:64
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
bool init(uint32 map_num, uint32 originalMapId)
Definition adtfile.cpp:76
bool initFromCache(uint32 map_num, uint32 originalMapId)
Definition adtfile.cpp:199
void seekRelative(int offset)
Definition cascfile.cpp:105
bool isEof()
Definition cascfile.h:45
char * getPointer()
Definition cascfile.h:44
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:42
void close()
Definition cascfile.cpp:111
ExtractedModelData const * 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:211
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) noexcept
Default TC string format function.
uint16 Flags
Definition adtfile.h:35
uint32 Id
Definition adtfile.h:30
uint16 Flags
Definition adtfile.h:45
uint32 Id
Definition adtfile.h:40
constexpr CStringBoundedSentinel< Iterator > Checked(Iterator end) const
Definition Util.h:394
ExtractedModelData const * ExtractSingleWmo(std::string &fname)
char const * szWorkDirWmo
@ MOD_PARENT_SPAWN
Definition vmapexport.h:30