forked from metin2/client
262 lines
5.3 KiB
C++
262 lines
5.3 KiB
C++
#include "StdAfx.h"
|
|
|
|
#include <fstream>
|
|
|
|
#include <io.h>
|
|
#include <assert.h>
|
|
|
|
#include "EterPackManager.h"
|
|
|
|
#include "../eterBase/Debug.h"
|
|
#include "../eterBase/CRC32.h"
|
|
|
|
#include "Folder.h"
|
|
#include "ZIP.h"
|
|
|
|
#define PATH_ABSOLUTE_YMIRWORK1 "d:/ymir work/"
|
|
#define PATH_ABSOLUTE_YMIRWORK2 "d:\\ymir work\\"
|
|
|
|
// StringPath std::string ¹öÀü
|
|
std::string CEterPackManager::ConvertFileName(std::string fileName)
|
|
{
|
|
std::string convertedFileName = fileName;
|
|
stl_lowers(convertedFileName);
|
|
|
|
for (DWORD i = 0; i < convertedFileName.length(); i++)
|
|
{
|
|
if (convertedFileName[i] == '\\')
|
|
convertedFileName[i] = '/';
|
|
}
|
|
|
|
return convertedFileName;
|
|
}
|
|
|
|
bool CEterPackManager::CompareName(const char * c_szDirectoryName, DWORD /*dwLength*/, const char * c_szFileName)
|
|
{
|
|
const char * c_pszSrc = c_szDirectoryName;
|
|
const char * c_pszCmp = c_szFileName;
|
|
|
|
while (*c_pszSrc)
|
|
{
|
|
if (*(c_pszSrc++) != *(c_pszCmp++))
|
|
return false;
|
|
|
|
if (!*c_pszCmp)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
struct TimeChecker
|
|
{
|
|
TimeChecker(const char* name) : name(name)
|
|
{
|
|
baseTime = timeGetTime();
|
|
}
|
|
~TimeChecker()
|
|
{
|
|
printf("load %s (%d)\n", name, timeGetTime() - baseTime);
|
|
}
|
|
|
|
const char* name;
|
|
DWORD baseTime;
|
|
};
|
|
|
|
bool CEterPackManager::Get(const std::string& fileName, TPackDataPtr& dataPtr)
|
|
{
|
|
//TimeChecker timeChecker(c_szFileName);
|
|
//Logf(1, "Load %s\n", c_szFileName);
|
|
|
|
if (m_iSearchMode == SEARCH_FILE_FIRST)
|
|
{
|
|
if (GetFromFile(fileName, dataPtr))
|
|
return true;
|
|
|
|
return GetFromPack(fileName, dataPtr);
|
|
}
|
|
|
|
if (GetFromPack(fileName, dataPtr))
|
|
return true;
|
|
|
|
return GetFromFile(fileName, dataPtr);
|
|
}
|
|
|
|
|
|
bool CEterPackManager::Get(const std::string& fileName, std::stringstream& dataStream)
|
|
{
|
|
CEterPackManager::TPackDataPtr data;
|
|
if (!Get(fileName, data))
|
|
return false;
|
|
|
|
// Copy the data from the pack into the file sstream
|
|
dataStream.str("");
|
|
std::copy(data->begin(), data->end(), std::ostream_iterator<char>(dataStream));
|
|
|
|
return true;
|
|
}
|
|
|
|
struct FinderLock
|
|
{
|
|
FinderLock(CRITICAL_SECTION& cs) : p_cs(&cs)
|
|
{
|
|
EnterCriticalSection(p_cs);
|
|
}
|
|
|
|
~FinderLock()
|
|
{
|
|
LeaveCriticalSection(p_cs);
|
|
}
|
|
|
|
CRITICAL_SECTION* p_cs;
|
|
};
|
|
|
|
bool CEterPackManager::GetFromPack(const std::string& fileName, TPackDataPtr& dataPtr)
|
|
{
|
|
FinderLock lock(m_csFinder);
|
|
|
|
std::string strFileName = ConvertFileName(fileName);
|
|
|
|
auto pkFileItem = m_FileMap.find(strFileName);
|
|
|
|
if (pkFileItem == m_FileMap.end()) {
|
|
#ifdef _DEBUG
|
|
TraceError("CANNOT_FIND_PACK_FILE [%s]", strFileName.c_str());
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
auto data = std::make_shared<std::vector<char>>();
|
|
if (!pkFileItem->second->getFile(strFileName, data))
|
|
return false;
|
|
|
|
// Set dataPtr to the retreived data pointer
|
|
dataPtr = data;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CEterPackManager::GetFromFile(const std::string& fileName, TPackDataPtr& dataPtr)
|
|
{
|
|
// Try to open the file
|
|
std::ifstream file(fileName, std::ios::binary);
|
|
if (!file.is_open())
|
|
return false;
|
|
|
|
// Read the file's contents
|
|
dataPtr = std::make_shared<std::vector<char>>(
|
|
std::istreambuf_iterator<char>(file),
|
|
std::istreambuf_iterator<char>()
|
|
);
|
|
return true;
|
|
}
|
|
|
|
bool CEterPackManager::isExistInPack(const char * c_szFileName)
|
|
{
|
|
std::string strFileName = ConvertFileName(c_szFileName);
|
|
|
|
auto pkFileItem = m_FileMap.find(strFileName);
|
|
|
|
if (pkFileItem == m_FileMap.end())
|
|
return false;
|
|
|
|
if (!pkFileItem->second)
|
|
return false;
|
|
|
|
return pkFileItem->second->fileExists(strFileName.c_str());
|
|
}
|
|
|
|
bool CEterPackManager::isExist(const char * c_szFileName)
|
|
{
|
|
if (m_iSearchMode == SEARCH_PACK_FIRST)
|
|
{
|
|
if (isExistInPack(c_szFileName))
|
|
return true;
|
|
|
|
return _access(c_szFileName, 0) == 0;
|
|
}
|
|
|
|
if (_access(c_szFileName, 0) == 0)
|
|
return true;
|
|
|
|
return isExistInPack(c_szFileName);
|
|
}
|
|
|
|
bool CEterPackManager::PackExists(const std::string& name, const std::string& container)
|
|
{
|
|
if (container == "FOLDER") {
|
|
return _access(name.c_str(), 0) == 0;
|
|
}
|
|
else if (container == "ZIP") {
|
|
std::string zipName = name + ".zip";
|
|
return _access(zipName.c_str(), 0) == 0;
|
|
}
|
|
|
|
throw std::runtime_error("Unexpected container type: " + container + "!");
|
|
}
|
|
|
|
bool CEterPackManager::RegisterPack(const std::string& name, const std::string& container)
|
|
{
|
|
auto it = m_PackMap.find(name);
|
|
|
|
if (it != m_PackMap.end())
|
|
return true;
|
|
|
|
try {
|
|
bool bReadOnly = true;
|
|
|
|
std::shared_ptr<FileProvider> pack;
|
|
|
|
// Determine requested container type
|
|
if (container == "FOLDER")
|
|
pack = std::make_shared<Folder>(name);
|
|
else if (container == "ZIP")
|
|
pack = std::make_shared<ZIP>(name + ".zip");
|
|
else
|
|
throw std::runtime_error("Unexpected container type: " + container + "!");
|
|
|
|
// Load container data
|
|
auto packFiles = pack->listFiles();
|
|
|
|
for (auto const& fileName : packFiles)
|
|
m_FileMap.insert({ fileName, pack });
|
|
|
|
m_PackMap.insert({ name, pack });
|
|
|
|
return true;
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
#ifdef _DEBUG
|
|
Tracef("Unable to load file provider '%s': %s\n", name.c_str(), e.what());
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void CEterPackManager::SetSearchMode(bool bPackFirst)
|
|
{
|
|
m_iSearchMode = bPackFirst ? SEARCH_PACK_FIRST : SEARCH_FILE_FIRST;
|
|
}
|
|
|
|
int CEterPackManager::GetSearchMode()
|
|
{
|
|
return m_iSearchMode;
|
|
}
|
|
|
|
CEterPackManager::CEterPackManager() : m_iSearchMode(SEARCH_FILE_FIRST)
|
|
{
|
|
InitializeCriticalSection(&m_csFinder);
|
|
}
|
|
|
|
CEterPackManager::~CEterPackManager()
|
|
{
|
|
DeleteCriticalSection(&m_csFinder);
|
|
}
|
|
|
|
const CEterPackManager::TFileMap& CEterPackManager::GetFileMap() {
|
|
return this->m_FileMap;
|
|
}
|