diff --git a/Client/mods/deathmatch/logic/CClientIFP.cpp b/Client/mods/deathmatch/logic/CClientIFP.cpp index 66b3280ec28..6595372648f 100644 --- a/Client/mods/deathmatch/logic/CClientIFP.cpp +++ b/Client/mods/deathmatch/logic/CClientIFP.cpp @@ -24,12 +24,12 @@ CClientIFP::CClientIFP(class CClientManager* pManager, ElementID ID) : CClientEn m_u32Hashkey = 0; } -bool CClientIFP::LoadIFP(const SString& strFilePath, const SString& strBlockName) +bool CClientIFP::LoadIFP(const SString& strFile, const bool isRawData, const SString& strBlockName) { m_strBlockName = strBlockName; m_pVecAnimations = &m_pIFPAnimations->vecAnimations; - if (LoadIFPFile(strFilePath)) + if (LoadIFPFile(strFile, isRawData)) { m_u32Hashkey = HashString(strBlockName.ToLower()); return true; @@ -37,9 +37,9 @@ bool CClientIFP::LoadIFP(const SString& strFilePath, const SString& strBlockName return false; } -bool CClientIFP::LoadIFPFile(const SString& strFilePath) +bool CClientIFP::LoadIFPFile(const SString& strFile, const bool isRawData) { - if (LoadFileToMemory(strFilePath)) + if (isRawData ? LoadDataBufferToMemory(strFile) : LoadFileToMemory(strFile)) { if (ReadIFPByVersion()) { diff --git a/Client/mods/deathmatch/logic/CClientIFP.h b/Client/mods/deathmatch/logic/CClientIFP.h index 57ddf9d805a..a740de88a96 100644 --- a/Client/mods/deathmatch/logic/CClientIFP.h +++ b/Client/mods/deathmatch/logic/CClientIFP.h @@ -205,7 +205,7 @@ class CClientIFP : public CClientEntity, CFileReader void MarkAsUnloading(void) { m_bUnloading = true; } bool IsUnloading(void) { return m_bUnloading; } - bool LoadIFP(const SString& strFilePath, const SString& strBlockName); + bool LoadIFP(const SString& strFile, const bool isRawData, const SString& strBlockName); const SString& GetBlockName(void) { return m_strBlockName; } const unsigned int& GetBlockNameHash(void) { return m_u32Hashkey; } @@ -219,7 +219,7 @@ class CClientIFP : public CClientEntity, CFileReader void SetPosition(const CVector& vecPosition){}; private: - bool LoadIFPFile(const SString& strFilePath); + bool LoadIFPFile(const SString& strFile, const bool isRawData); bool ReadIFPByVersion(void); void ReadIFPVersion1(void); void ReadIFPVersion2(bool bAnp3); diff --git a/Client/mods/deathmatch/logic/CFileReader.cpp b/Client/mods/deathmatch/logic/CFileReader.cpp index e99c037132c..e5838defde1 100644 --- a/Client/mods/deathmatch/logic/CFileReader.cpp +++ b/Client/mods/deathmatch/logic/CFileReader.cpp @@ -45,15 +45,31 @@ void CFileReader::SkipBytes(const std::uint32_t u32BytesToSkip) bool CFileReader::LoadFileToMemory(const SString& strFilePath) { std::ifstream fileStream(FromUTF8(strFilePath), std::ios::binary | std::ios::ate); - std::streamsize m_iFileSize = fileStream.tellg(); - if (m_iFileSize == eIFSTREAM::SIZE_ERROR) + std::streamsize iFileSize = fileStream.tellg(); + if (iFileSize == eIFSTREAM::SIZE_ERROR) { return false; } fileStream.seekg(0, std::ios::beg); - m_vecFileDataBuffer.reserve(static_cast(m_iFileSize)); - if (fileStream.read(m_vecFileDataBuffer.data(), m_iFileSize)) + m_vecFileDataBuffer.reserve(static_cast(iFileSize)); + if (fileStream.read(m_vecFileDataBuffer.data(), iFileSize)) + { + return true; + } + return false; +} + +bool CFileReader::LoadDataBufferToMemory(const SString& buffer) +{ + std::streamsize iBufferSize = buffer.size(); + if (iBufferSize == eIFSTREAM::SIZE_ERROR) + { + return false; + } + + m_vecFileDataBuffer.reserve(static_cast(iBufferSize)); + if (std::copy(buffer.begin(), buffer.end(), m_vecFileDataBuffer.data())) { return true; } diff --git a/Client/mods/deathmatch/logic/CFileReader.h b/Client/mods/deathmatch/logic/CFileReader.h index c99977a5e7d..1cc6c646787 100644 --- a/Client/mods/deathmatch/logic/CFileReader.h +++ b/Client/mods/deathmatch/logic/CFileReader.h @@ -24,6 +24,7 @@ class CFileReader CFileReader(void); bool LoadFileToMemory(const SString& strFilePath); + bool LoadDataBufferToMemory(const SString& buffer); // Do not call any file reader functions after calling this function void FreeFileReaderMemory(void); diff --git a/Client/mods/deathmatch/logic/CIFPEngine.cpp b/Client/mods/deathmatch/logic/CIFPEngine.cpp index 28ec602f91b..1035e186a18 100644 --- a/Client/mods/deathmatch/logic/CIFPEngine.cpp +++ b/Client/mods/deathmatch/logic/CIFPEngine.cpp @@ -10,7 +10,7 @@ #include -std::shared_ptr CIFPEngine::EngineLoadIFP(CResource* pResource, CClientManager* pManager, const SString& strPath, const SString& strBlockName) +std::shared_ptr CIFPEngine::EngineLoadIFP(CResource* pResource, CClientManager* pManager, const SString& strFile, bool bIsRawData, const SString& strBlockName) { // Grab the resource root entity CClientEntity* pRoot = pResource->GetResourceIFPRoot(); @@ -23,7 +23,7 @@ std::shared_ptr CIFPEngine::EngineLoadIFP(CResource* pResource, CCli std::shared_ptr pIFP(new CClientIFP(pManager, INVALID_ELEMENT_ID)); // Try to load the IFP file - if (pIFP->LoadIFP(strPath, strBlockName)) + if (pIFP->LoadIFP(strFile, bIsRawData, strBlockName)) { // We can use the map to retrieve correct IFP by block name later g_pClientGame->InsertIFPPointerToMap(u32BlockNameHash, pIFP); @@ -99,3 +99,9 @@ bool CIFPEngine::EngineRestoreAnimation(CClientEntity* pEntity, const SString& s } return false; } + +// Return true if data looks like IFP file contents +bool CIFPEngine::IsIFPData(const SString& strData) +{ + return strData.length() > 32 && memcmp(strData, "\x41\x4E\x50", 3) == 0; +} diff --git a/Client/mods/deathmatch/logic/CIFPEngine.h b/Client/mods/deathmatch/logic/CIFPEngine.h index 711371112a4..160cba5a1bb 100644 --- a/Client/mods/deathmatch/logic/CIFPEngine.h +++ b/Client/mods/deathmatch/logic/CIFPEngine.h @@ -25,11 +25,12 @@ class CIFPEngine ALL }; - static std::shared_ptr EngineLoadIFP(CResource* pResource, CClientManager* pManager, const SString& strPath, const SString& strBlockName); + static std::shared_ptr EngineLoadIFP(CResource* pResource, CClientManager* pManager, const SString& strFile, bool bIsRawData, const SString& strBlockName); static bool EngineReplaceAnimation(CClientEntity* pEntity, const SString& strInternalBlockName, const SString& strInternalAnimName, const SString& strCustomBlockName, const SString& strCustomAnimName); static bool EngineRestoreAnimation(CClientEntity* pEntity, const SString& strInternalBlockName, const SString& strInternalAnimName, const eRestoreAnimation& eRestoreType); + static bool IsIFPData(const SString& strData); }; #endif diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp index d7c7e921d9e..154fcbe62d3 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaEngineDefs.cpp @@ -297,11 +297,12 @@ int CLuaEngineDefs::EngineLoadIFP(lua_State* luaVM) CResource* pResource = pLuaMain->GetResource(); if (pResource) { + bool bIsRawData = CIFPEngine::IsIFPData(strFile); SString strPath; // Is this a legal filepath? - if (CResourceManager::ParseResourcePathInput(strFile, pResource, &strPath)) + if (bIsRawData || CResourceManager::ParseResourcePathInput(strFile, pResource, &strPath)) { - std::shared_ptr pIFP = CIFPEngine::EngineLoadIFP(pResource, m_pManager, strPath, strBlockName); + std::shared_ptr pIFP = CIFPEngine::EngineLoadIFP(pResource, m_pManager, bIsRawData ? strFile : strPath, bIsRawData, strBlockName); if (pIFP != nullptr) { // Return the IFP element @@ -309,10 +310,10 @@ int CLuaEngineDefs::EngineLoadIFP(lua_State* luaVM) return 1; } else - argStream.SetCustomError(strFile, "Error loading IFP"); + argStream.SetCustomError(bIsRawData ? "raw data" : strFile, "Error loading IFP"); } else - argStream.SetCustomError(strFile, "Bad file path"); + argStream.SetCustomError(bIsRawData ? "raw data" : strFile, "Bad file path"); } } }