diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 4a8dc3d9..d3988206 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -389,16 +389,15 @@ namespace Components std::string path = Dvar::Var("fs_basepath").get() + "\\usermaps\\" + mapname; - std::vector list = { mapname + ".ff", mapname + "_load.ff", mapname + ".iwd" }; - for (auto i = list.begin(); i != list.end(); ++i) + for (int i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) { - std::string filename = path + "\\" + *i; - if (strstr(i->data(), "_svr_") == nullptr && Utils::IO::FileExists(filename)) + std::string filename = path + "\\" + mapname + Maps::UserMapFiles[i]; + if (Utils::IO::FileExists(filename)) { std::map file; std::string fileBuffer = Utils::IO::ReadFile(filename); - file["name"] = *i; + file["name"] = mapname + Maps::UserMapFiles[i]; file["size"] = static_cast(fileBuffer.size()); file["hash"] = Utils::Cryptography::SHA256::Compute(fileBuffer, true); @@ -506,7 +505,18 @@ namespace Components url = url.substr(4); std::string mapname = Maps::GetUserMap()->getName(); - if(!Maps::GetUserMap()->isValid() || (url != (mapname + ".ff") && url != (mapname + ".iwd") && url != (mapname + "_load.ff"))) + + bool isValidFile = false; + for (int i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) + { + if(url == (mapname + Maps::UserMapFiles[i])) + { + isValidFile = true; + break; + } + } + + if(!Maps::GetUserMap()->isValid() || !isValidFile) { Download::Forbid(nc); return; @@ -702,7 +712,7 @@ namespace Components // Handle special requests mg_register_http_endpoint(nc, "/info", Download::InfoHandler); mg_register_http_endpoint(nc, "/list", Download::ListHandler); - mg_register_http_endpoint(nc, "/map", Download::MapHandler); + mg_register_http_endpoint(nc, "/map", Download::MapHandler); mg_register_http_endpoint(nc, "/file/", Download::FileHandler); mg_set_protocol_http_websocket(nc); diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index a63d8220..60d2976c 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -12,6 +12,14 @@ namespace Components std::vector Maps::DlcPacks; std::vector Maps::EntryPool; + const char* Maps::UserMapFiles[4] = + { + ".ff", + "_load.ff", + ".iwd", + ".arena", + }; + Maps::UserMapContainer* Maps::GetUserMap() { return &Maps::UserMap; @@ -83,6 +91,25 @@ namespace Components } } + const char* Maps::LoadArenaFileStub(const char* name, char* buffer, int size) + { + std::string data = Game::LoadModdableRawfile(0, name); + + if(Maps::UserMap.isValid()) + { + std::string mapname = Maps::UserMap.getName(); + std::string arena = Utils::String::VA("usermaps/%s/%s.arena", mapname.data(), mapname.data()); + + if (Utils::IO::FileExists(arena)) + { + data.append(Utils::IO::ReadFile(arena)); + } + } + + strncpy_s(buffer, size, data.data(), data.size()); + return buffer; + } + void Maps::UnloadMapZones(Game::XZoneInfo* zoneInfo, unsigned int zoneCount, int sync) { Game::DB_LoadXAssets(zoneInfo, zoneCount, sync); @@ -396,21 +423,18 @@ namespace Components { if (Utils::IO::DirectoryExists(Utils::String::VA("usermaps/%s", map.data()))) { - std::string zoneHash; - std::string zonePath = Utils::String::VA("usermaps/%s/%s.ff", map.data(), map.data()); - if (Utils::IO::FileExists(zonePath)) + std::string hash; + + for(int i = 0; i < ARRAYSIZE(Maps::UserMapFiles); ++i) { - zoneHash = Utils::Cryptography::SHA256::Compute(Utils::IO::ReadFile(zonePath)); + std::string filePath = Utils::String::VA("usermaps/%s/%s%s", map.data(), map.data(), Maps::UserMapFiles[i]); + if (Utils::IO::FileExists(filePath)) + { + hash.append(Utils::Cryptography::SHA256::Compute(Utils::IO::ReadFile(filePath))); + } } - std::string iwdHash; - std::string iwdPath = Utils::String::VA("usermaps/%s/%s.iwd", map.data(), map.data()); - if (Utils::IO::FileExists(iwdPath)) - { - iwdHash = Utils::Cryptography::SHA256::Compute(Utils::IO::ReadFile(iwdPath)); - } - - return Utils::Cryptography::JenkinsOneAtATime::Compute(zoneHash + iwdHash); + return Utils::Cryptography::JenkinsOneAtATime::Compute(hash); } return 0; @@ -871,6 +895,9 @@ namespace Components // Conflicts with Theater's SV map rotation check, but this one is safer! Utils::Hook(0x5AA91C, Maps::RotateCheckStub, HOOK_CALL).install()->quick(); + // Load usermap arena file + Utils::Hook(0x630A88, Maps::LoadArenaFileStub, HOOK_CALL).install()->quick(); + Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP, 1); Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, 7168); Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700); diff --git a/src/Components/Modules/Maps.hpp b/src/Components/Modules/Maps.hpp index 14baf21e..072af76f 100644 --- a/src/Components/Modules/Maps.hpp +++ b/src/Components/Modules/Maps.hpp @@ -8,11 +8,12 @@ namespace Components class UserMapContainer { public: - UserMapContainer() : wasFreed(false) { } + UserMapContainer() : wasFreed(false), hash(0) {} UserMapContainer(std::string _mapname) : wasFreed(false), mapname(_mapname) { ZeroMemory(&this->searchPath, sizeof this->searchPath); this->hash = Maps::GetUsermapHash(this->mapname); + Game::UI_UpdateArenas(); } ~UserMapContainer() @@ -24,7 +25,12 @@ namespace Components unsigned int getHash() { return this->hash; } std::string getName() { return this->mapname; } bool isValid() { return !this->mapname.empty(); } - void clear() { this->mapname.clear(); } + void clear() + { + bool wasValid = this->isValid(); + this->mapname.clear(); + if(wasValid) Game::UI_UpdateArenas(); + } void loadIwd(); void freeIwd(); @@ -54,6 +60,7 @@ namespace Components static std::vector GetDependenciesForMap(std::string map); static std::string CurrentMainZone; + static const char* UserMapFiles[4]; static bool CheckMapInstalled(const char* mapname, bool error = false, bool dlcIsTrue = false); @@ -105,6 +112,8 @@ namespace Components static int TriggerReconnectForMap(const char* mapname); static void RotateCheckStub(); + static const char* LoadArenaFileStub(const char* name, char* buffer, int size); + void reallocateEntryPool(); }; } diff --git a/src/Components/Modules/RawFiles.cpp b/src/Components/Modules/RawFiles.cpp index 486b059e..f542da6d 100644 --- a/src/Components/Modules/RawFiles.cpp +++ b/src/Components/Modules/RawFiles.cpp @@ -13,7 +13,7 @@ namespace Components Utils::Hook(0x5FA46C, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x5FA4D6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x6321EF, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); - Utils::Hook(0x630A88, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); + //Utils::Hook(0x630A88, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); // Arena parsing, handled by usermap hook Utils::Hook(0x59A6F8, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x57F1E6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick(); Utils::Hook(0x57ED36, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).install()->quick();