18 m_CASCFolder.init(path());
24 std::ifstream file(fullPath);
27 LOG_ERROR <<
"Failed to open" << filename;
32 file.seekg(0, std::ios::end);
33 const auto totalSize = file.tellg();
34 file.seekg(0, std::ios::beg);
37 LOG_INFO <<
"WoWFolder - Starting to build object hierarchy";
39 while (std::getline(file, stdline))
43 if (lineData.size() < 2)
45 int id = std::stoi(lineData[0]);
46 std::string fileName = lineData[1];
49 m_idNameMap[id] = fileName;
50 m_nameIdMap[fileName] = id;
51 if (m_CASCFolder.fileExists(
id))
54 auto lastSlash = line.rfind(
'/');
55 File->
setName(lastSlash != std::string::npos ? line.substr(lastSlash + 1) : line);
58 if (m_progressCallback && ++lineCount % 500 == 0 && totalSize > 0)
59 m_progressCallback(
static_cast<int>(file.tellg()),
static_cast<int>(totalSize));
61 LOG_INFO <<
"WoWFolder - Hierarchy creation done";
66 LOG_INFO <<
"Add customFiles from folder" << path;
67 namespace fs = std::filesystem;
70 for (
const auto& entry : fs::recursive_directory_iterator(path, ec))
72 if (!entry.is_regular_file())
76 std::string absPath = filePath;
78 std::string toRemove = path +
"\\";
79 if (filePath.find(toRemove) == 0)
80 filePath.erase(0, toRemove.size());
82 GameFile* originalFile = GameFolder::getFile(filePath);
83 bool addnewfile =
true;
87 if (bypassOriginalFiles)
90 removeChild(originalFile);
92 originalFile =
nullptr;
103 auto it = m_nameIdMap.find(filePath);
104 if (it != m_nameIdMap.end())
105 originalId = it->second;
109 LOG_INFO <<
"Add custom file" << filePath <<
"(ID:" << originalId <<
")from hard drive location" <<
112 auto lastSlash = filePath.rfind(
'/');
113 file->
setName(lastSlash != std::string::npos ? filePath.substr(lastSlash + 1) : filePath);
126 const auto it = m_idMap.find(
id);
127 if (it != m_idMap.end())
133 const std::string filename = std::format(
"File{:08x}.unk",
id);
134 LOG_INFO <<
"File with id" <<
id <<
"not found in listfile. Trying to open" << filename;
137 if (m_CASCFolder.openFile(
id, &newfile))
140 m_CASCFolder.closeFile(newfile);
153 return m_CASCFolder.
openFile(
id, result);
158 const auto it = m_nameIdMap.find(file);
159 if (it == m_nameIdMap.end())
161 return m_CASCFolder.openFile(it->second, result);
166 return m_CASCFolder.version();
172 return std::stoi(v[0]);
177 return m_CASCFolder.locale();
182 return m_CASCFolder.setConfig(config);
187 return m_CASCFolder.configsFound();
192 return m_CASCFolder.lastError();
197 GameFolder::onChildAdded(child);
203 GameFolder::onChildRemoved(child);
209 const auto it = m_idNameMap.find(
id);
210 if (it == m_idNameMap.end())
211 return std::string();
217 const auto it = m_nameIdMap.find(fileName);
218 if (it == m_nameIdMap.end())
GameFile implementation that reads from a CASC storage archive.
void setName(const std::string &name)
Abstract base class representing a file within the game data archive.
virtual bool openFile()=0
A CASCFile implementation that reads data from the local hard drive rather than from a CASC archive.
Describes a detected game installation (locale, version, product).
static Game & instance()
Access the singleton instance (Meyers singleton).
std::string configFolder()
GameFile * getFile(int id) override
std::string fileName(int id)
int majorVersion() override
void initFromListfile(const std::string &file) override
WoWFolder(const std::string &path)
int fileID(const std::string &fileName)
void onChildAdded(GameFile *) override
void onChildRemoved(GameFile *) override
std::vector< core::GameConfig > configsFound() override
bool openFile(int id, HANDLE *result) override
void addCustomFiles(const std::string &path, bool bypassOriginalFiles) override
bool setConfig(core::GameConfig config) override
std::string version() override
std::string locale() override
std::vector< std::string > split(const std::string &s, char delimiter)
Split a string by a single-character delimiter.
std::string toLower(const std::string &s)