#include "SWrapper.h" #include #include #include #include "spdlog/spdlog.h" #include namespace fs = std::filesystem; SWrapper::SWrapper(const std::string& path) { mPath = path; } int32_t SWrapper::CreateArchive() { #ifndef USE_STORMLIB throw std::runtime_error("StormLib is not enabled. Cannot create archive"); #else if(fs::exists(mPath)) { fs::remove(mPath); } if(!SFileCreateArchive(mPath.c_str(), MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES | MPQ_CREATE_ARCHIVE_V2, 16 * 1024, &this->hMpq)){ SPDLOG_ERROR("Failed to create archive {} with error code {}", mPath, GetLastError()); return -1; } return 0; #endif } bool SWrapper::AddFile(const std::string& path, std::vector data) { #ifndef USE_STORMLIB throw std::runtime_error("StormLib is not enabled. Cannot create file"); #else if(Companion::Instance != nullptr && Companion::Instance->IsDebug()){ SPDLOG_INFO("Creating debug file: debug/{}", path); std::string dpath = "debug/" + path; if(!fs::exists(fs::path(dpath).parent_path())){ fs::create_directories(fs::path(dpath).parent_path()); } std::ofstream stream(dpath, std::ios::binary); stream.write((char*)data.data(), data.size()); stream.close(); } HANDLE hFile; #ifdef _WIN32 SYSTEMTIME sysTime; GetSystemTime(&sysTime); FILETIME t; SystemTimeToFileTime(&sysTime, &t); ULONGLONG theTime = static_cast(t.dwHighDateTime) << (sizeof(t.dwHighDateTime) * 8) | t.dwLowDateTime; #else time_t theTime; time(&theTime); #endif char* raw = data.data(); size_t size = data.size(); if(size == 0){ SPDLOG_ERROR("File at path {} is empty", path); return false; } if(size >> 32){ throw std::runtime_error("File at path " + path + " is too large with size " + std::to_string(size)); } if(!SFileCreateFile(this->hMpq, path.c_str(), theTime, size, 0, MPQ_FILE_COMPRESS, &hFile)){ return false; } if(!SFileWriteFile(hFile, (void*) raw, size, MPQ_COMPRESSION_ZLIB)){ throw std::runtime_error("Failed to write file at path " + path + " with error " + std::to_string(GetLastError())); } if(!SFileCloseFile(hFile)){ throw std::runtime_error("Failed to close file at path " + path + " with error " + std::to_string(GetLastError())); } return true; #endif } int32_t SWrapper::Close(void) { #ifndef USE_STORMLIB throw std::runtime_error("StormLib is not enabled. Cannot close archive"); #else if(this->hMpq == nullptr) { SPDLOG_ERROR("Archive already closed"); return -1; } if (SFileCloseArchive(this->hMpq)) { SPDLOG_ERROR("Error closing archive"); return -1; } return 0; #endif }