Files
Client/Tools/NeoPatchMaker/PatchMaker.cpp
LGram16 e067522598 Initial commit: ROW Client source code
Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 16:24:34 +09:00

780 lines
21 KiB
C++

// PatchMaker.cpp: implementation of the CPatchMaker class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NeoPatchMaker.h"
#include "PatchMaker.h"
#include "Crc32Static.h"
#include "afxinet.h"
#include "set"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////////
//
CPatchMaker::CPatchMaker()
{
m_PatchmakerState = PMS_IDLE;
}
CPatchMaker::~CPatchMaker()
{
}
bool CPatchMaker::Go( CEdit* pEditOutput )
{
//////////////////////////////////////////////////////////////////////////
// 변수 초기화
m_ZipArc.Close();
m_arrIndexToUpdateLocalFile.RemoveAll();
m_LocalPatchInfo.Reset();
m_ServerPatchInfo.Reset();
m_strCurrentNewPackageFileName = "";
m_astrFileNameWithSubDirExclusionList.RemoveAll();
m_astrFileNameExclusionList.RemoveAll();
m_astrSubDirExclusionList.RemoveAll();
m_ZipArc.SetCaseSensitivity( false );
//////////////////////////////////////////////////////////////////////////
// 초기값 설정(Test only)
// m_dwPackageMaxSize = 500 * 1024; // 500kbytes, 0.5MB
//
// m_strPackageFilePath = "F:\\FilePatchTest\\";
// m_strLocalFilePath = "F:\\RYL\\Risk Your Life (Test Server Version)\\";
// m_strDestFilePath = "F:\\FilePatchTest\\modified\\";
// m_SourceType = FILE_ON_LOCAL;
// m_DestType = FILE_ON_LOCAL;
// m_dwUpdateVersion = 352;
//
// m_strFTPServerAddr = "211.233.42.245";
// m_strFTPAccount = "ryl";
// m_strFTPPassword = "fldjzk!$";
//////////////////////////////////////////////////////////////////////////
// validity check (path seperator, FTP connectivity)
pEditOutput->SetWindowText( "0. Check validity" );
if( false == CheckValidity( pEditOutput ) )
{
pEditOutput->SetWindowText( "Faild (Check validity)" );
return false;
}
//////////////////////////////////////////////////////////////////////////
// server patch info 읽어들임
m_PatchmakerState = PMS_LOAD_SERVER_PATCHINFO_LIST;
pEditOutput->SetWindowText( "1. Loading previous version patchinfo list" );
if( false == LoadServerPatchInfoList() )
{
pEditOutput->SetWindowText( "Faild (Loading previous version patchinfo list)" );
m_PatchmakerState = PMS_IDLE;
return false;
}
//////////////////////////////////////////////////////////////////////////
// local patch info 작성
m_PatchmakerState = PMS_BUILD_LOCAL_PATCHINFO_LIST;
pEditOutput->SetWindowText( "2. Building local patchinfo list" );
if( false == BuildLocalPatchInfoList() )
{
pEditOutput->SetWindowText( "Faild (Building local patchinfo list)" );
m_PatchmakerState = PMS_IDLE;
return false;
}
//////////////////////////////////////////////////////////////////////////
// 기존 패키지 내 파일 중 업데이트 할 파일 & 새로 패키지화되어야 할 파일 목록 작성
m_PatchmakerState = PMS_COLLECT_UPDATE_FILE_LIST;
pEditOutput->SetWindowText( "3. Compare & collecting update file list" );
if( false == CollectUpdateFileList() )
{
pEditOutput->SetWindowText( "Faild (Compare & collecting update file list)" );
m_PatchmakerState = PMS_IDLE;
return false;
}
//////////////////////////////////////////////////////////////////////////
// 패키지 파일 업데이트 & 신규 패키지 작성
m_PatchmakerState = PMS_UPDATE_PACKAGE;
pEditOutput->SetWindowText( "4. Updating & creating package(.zip) file" );
if( false == UpdatePackage() )
{
pEditOutput->SetWindowText( "Faild (Updating & creating package(.zip) file)" );
m_PatchmakerState = PMS_IDLE;
return false;
}
//////////////////////////////////////////////////////////////////////////
// PatchInfo 파일 저장&압축
m_PatchmakerState = PMS_UPDATE_PATCHINFO;
pEditOutput->SetWindowText( "5. Updating patchinfo file" );
if( false == UpdatePatchInfo() )
{
pEditOutput->SetWindowText( "Faild (Updating patchinfo file)" );
m_PatchmakerState = PMS_IDLE;
return false;
}
//////////////////////////////////////////////////////////////////////////
// Clear
pEditOutput->SetWindowText( "-- Finished --" );
return true;
}
//////////////////////////////////////////////////////////////////////////
// validity check (path seperator, FTP connectivity)
bool CPatchMaker::CheckValidity( CEdit* pEditOutput )
{
// 이전버전 패키지 디렉토리명 끝의 seperator 확인
if( m_strPackageFilePath.GetLength() )
{
if( FILE_ON_FTP == m_SourceType )
{
if( m_strPackageFilePath.Right(1) != "/" )
{
m_strPackageFilePath += "/";
}
}
if( FILE_ON_LOCAL == m_SourceType )
{
if( m_strPackageFilePath.Right(1) != "\\" )
{
m_strPackageFilePath += "\\";
}
}
}
else
{
return false;
}
if( m_strLocalFilePath.GetLength() )
{
if( m_strLocalFilePath.Right(1) != "\\" )
{
m_strLocalFilePath += "\\";
}
}
else
{
return false;
}
if( m_strDestFilePath.GetLength() )
{
if( FILE_ON_FTP == m_DestType )
{
if( m_strDestFilePath.Right(1) != "/" )
{
m_strDestFilePath += "/";
}
}
if( FILE_ON_LOCAL == m_DestType )
{
if( m_strDestFilePath.Right(1) != "\\" )
{
m_strDestFilePath += "\\";
}
}
}
else
{
return false;
}
BOOL bFTPSettingOK = TRUE;
if( FILE_ON_FTP == m_SourceType )
{
CInternetSession isess;
CFtpConnection* pFtp = isess.GetFtpConnection( m_strFTPServerAddr, m_strFTPAccount, m_strFTPPassword, m_nFTPPort, m_bPassiveMode );
bFTPSettingOK = pFtp->SetCurrentDirectory( m_strPackageFilePath );
pFtp->Close();
isess.Close();
}
if( FALSE == bFTPSettingOK )
{
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// server patch info 읽어들임
bool CPatchMaker::LoadServerPatchInfoList()
{
switch( m_SourceType )
{
case FILE_NONE:
return true;
break;
case FILE_ON_FTP:
{
CInternetSession isess;
CFtpConnection* pFtp = isess.GetFtpConnection( m_strFTPServerAddr, m_strFTPAccount, m_strFTPPassword, m_nFTPPort, m_bPassiveMode);
pFtp->SetCurrentDirectory( m_strPackageFilePath );
pFtp->GetFile( "PatchInfoV2.zip", m_strDestFilePath+"PatchInfoV2.zip" );
pFtp->Close();
isess.Close();
}
break;
case FILE_ON_LOCAL:
CopyFile( m_strPackageFilePath+"PatchInfoV2.zip", m_strDestFilePath+"PatchInfoV2.zip", FALSE );
break;
}
// PatchInfo 압축해제후 압축파일 삭제
CZipArchive zipArc;
zipArc.Open( m_strDestFilePath+"PatchInfoV2.zip", CZipArchive::zipOpen );
zipArc.ExtractFile( 0, m_strDestFilePath, false, "PatchInfoV2" );
zipArc.Close();
DeleteFile( m_strDestFilePath+"PatchInfoV2.zip" );
// PatchInfo 로드
m_ServerPatchInfo.Reset();
m_ServerPatchInfo.Load( m_strDestFilePath+"PatchInfoV2" );
DeleteFile( m_strDestFilePath+"PatchInfoV2");
// filename-to-index map 생성
for( size_t i = 0; i < m_ServerPatchInfo.GetList().size(); ++i )
{
long lTmp = m_mapFileName2ServerListIndex.size();
m_mapFileName2ServerListIndex[ m_ServerPatchInfo.GetList()[i].szFileName ] = lTmp;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// local patch info 작성
bool CPatchMaker::BuildLocalPatchInfoList()
{
WIN32_FIND_DATA w32fd;
HANDLE hFind = FindFirstFile( m_strLocalFilePath+"*.*", &w32fd );
if( INVALID_HANDLE_VALUE == hFind )
{
return false;
}
CString strCurrentSubPath("");
CStringArray astrSubDirList;
while( 1 )
{
if( !IsExcludedFileWithSubDir(strCurrentSubPath+w32fd.cFileName) &&
!IsExcludedFile( w32fd.cFileName ) )
{
if( w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
CString strTmp;
strTmp.Format( "%s%s", strCurrentSubPath, w32fd.cFileName );
if( !IsExcludedSubDir( strTmp ) )
{
astrSubDirList.Add( strTmp );
}
}
else
{
FilePatchInfoRecord fpir;
strcpy( fpir.szFileName, strCurrentSubPath+w32fd.cFileName );
CString strFullPathName = m_strLocalFilePath+strCurrentSubPath+w32fd.cFileName;
m_strStateInfoString.Format( "새 버전의 %s 파일을 검사중", strFullPathName );
CCrc32Static::FileCrc32Assembly( strFullPathName, fpir.dwCRC32 );
HANDLE hFile = CreateFile( strFullPathName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
fpir.dwSize = GetFileSize ( hFile, NULL );
CloseHandle( hFile );
m_LocalPatchInfo.GetList().push_back( fpir );
//m_mapFileName2LocalListIndex[fpir.szFileName] = m_LocalPatchInfo.GetList().size() - 1;
}
}
if( 0 == FindNextFile( hFind, &w32fd ) )
{
FindClose( hFind );
// sub dir queue 에 순서를 기다리고 있는 놈이 존재하면
if( astrSubDirList.GetSize() > 0 )
{
// 꺼내서 쓰고
strCurrentSubPath = astrSubDirList[0] + "\\";
astrSubDirList.RemoveAt(0);
hFind = FindFirstFile( m_strLocalFilePath+strCurrentSubPath+"*.*", &w32fd );
}
else
{
// 없음 루프 종료
break;
}
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// 기존 패키지 내 파일 중 업데이트 할 파일 & 새로 패키지화되어야 할 파일 목록 작성
bool CPatchMaker::CollectUpdateFileList()
{
size_t i = 0, max = m_LocalPatchInfo.GetList().size();
for( i = 0; i < max; ++i )
{
FilePatchInfoRecord &rLocalItem = m_LocalPatchInfo.GetList()[i];
// bool bFound = false;
// for( j = 0; j < m_ServerPatchInfo.GetList().size(); ++j )
// {
// FilePatchInfoRecord &rServerItem = m_ServerPatchInfo.GetList()[j];
//
// // 기존 패키지에 존재하는 파일일 경우(로컬 파일이 서버 리스트에서 발견된 경우)
// if( 0 == stricmp( rLocalItem.szFileName, rServerItem.szFileName ) )
// {
// bFound = true;
// strcpy( rLocalItem.szPackageFileName, rServerItem.szPackageFileName );
//
// // size와 CRC32 체크해 다르면 업데이트 대상에 등록
// if( rLocalItem.dwCRC32 != rServerItem.dwCRC32 ||
// rLocalItem.dwSize != rServerItem.dwSize )
// {
// m_arrIndexToUpdateLocalFile.Add( i );
//
// rLocalItem.dwVersion = m_dwUpdateVersion;
// }
// else
// {
// rLocalItem.dwVersion = rServerItem.dwVersion;
// }
//
// break;
// }
//
// }
//
// // 기존 패키지에 존재하지 않는 파일
// if( false == bFound )
// {
// m_arrIndexToUpdateLocalFile.Add( i );
//
// rLocalItem.dwVersion = m_dwUpdateVersion;
// }
std::map< PTR_STRING, int, PTR_STRING_LESS >::iterator it;
it = m_mapFileName2ServerListIndex.find( rLocalItem.szFileName );
if( m_mapFileName2ServerListIndex.end() == it )
{
// 기존 패키지에 존재하지 않는 파일
m_arrIndexToUpdateLocalFile.Add( i );
rLocalItem.dwVersion = m_dwUpdateVersion;
}
else
{
long lIdx = it->second;
FilePatchInfoRecord &rServerItem = m_ServerPatchInfo.GetList()[it->second];
strcpy( rLocalItem.szPackageFileName, rServerItem.szPackageFileName );
// size와 CRC32 체크해 다르면 업데이트 대상에 등록
if( rLocalItem.dwCRC32 != rServerItem.dwCRC32 ||
rLocalItem.dwSize != rServerItem.dwSize )
{
m_arrIndexToUpdateLocalFile.Add( i );
rLocalItem.dwVersion = m_dwUpdateVersion;
}
else
{
rLocalItem.dwVersion = rServerItem.dwVersion;
}
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// 패키지 파일 업데이트 & 신규 패키지 작성
bool CPatchMaker::UpdatePackage()
{
int i;
std::set<CString> setUpdatePackageFileList;
for( i = 0; i < m_arrIndexToUpdateLocalFile.GetSize(); ++i )
{
FilePatchInfoRecord &rFpir = m_LocalPatchInfo.GetList()[ m_arrIndexToUpdateLocalFile[i] ];
if( '\0' != rFpir.szPackageFileName[0] ) // 패키지 파일 이름이 빈 문자열이 아닐 경우(이미 패키지에 들어가 있는 파일)
{
// 받아올 패키지 파일 목록에 이미 등록되어있는지 확인(없으면 추가)
setUpdatePackageFileList.insert( CString(rFpir.szPackageFileName) );
}
}
// 패키지 파일 복사(혹은 다운로드)
std::set<CString>::iterator it;
switch( m_SourceType )
{
case FILE_ON_LOCAL:
{
// copy packages from src to dest
for(it = setUpdatePackageFileList.begin();
it != setUpdatePackageFileList.end(); ++it )
{
CString &rstr = *it;
CopyFile( m_strPackageFilePath+(*it)+".zip", m_strDestFilePath+(*it)+".zip", FALSE );
}
}
break;
case FILE_ON_FTP:
{
CInternetSession isess;
CFtpConnection* pFtp = isess.GetFtpConnection( m_strFTPServerAddr, m_strFTPAccount, m_strFTPPassword, m_nFTPPort, m_bPassiveMode );
pFtp->SetCurrentDirectory( m_strPackageFilePath );
for(it = setUpdatePackageFileList.begin(); it != setUpdatePackageFileList.end(); ++it )
{
pFtp->GetFile( (*it)+".zip", m_strDestFilePath+(*it)+".zip" );
Sleep(1);
}
pFtp->Close();
isess.Close();
}
break;
}
// package update, 혹은 신규 package 작성
for( i = 0; i < m_arrIndexToUpdateLocalFile.GetSize(); ++i )
{
Sleep(1);
FilePatchInfoRecord &rFpir = m_LocalPatchInfo.GetList()[ m_arrIndexToUpdateLocalFile[i] ];
if( '\0' == rFpir.szPackageFileName[0] )
{
// 파일의 패키지 이름 필드가 비어 있으면 -> 신규 or 마지막 패키지에 추가
//
// 주의 : 패키지 이름 필드가 비어 있다고 해서 항상 신규 패키지를 만드는게 아니다.
// 최근에 만든 신규 패키지가 다 채워지지 않았으면 거기에 들어가는 것임
if( m_strCurrentNewPackageFileName == "" )
{
// 패키지 파일을 신규로 만들거나
m_strCurrentNewPackageFileName = GetNextPackageFileName();
m_ZipArc.Open( m_strDestFilePath+m_strCurrentNewPackageFileName+".zip", CZipArchive::zipCreate );
}
else
{
// granular 용량이 다 채워지지않은 패키지가 마지막일 경우 그것을 오픈
m_ZipArc.Open( m_strDestFilePath+m_strCurrentNewPackageFileName+".zip", CZipArchive::zipOpen );
}
m_ZipArc.SetRootPath( m_strLocalFilePath );
CZipAddNewFileInfo zanfi( m_strLocalFilePath+rFpir.szFileName, false );
zanfi.Defaults();
m_ZipArc.AddNewFile( zanfi );
m_ZipArc.Close();
// patchinfo 에 기록될 패키지 이름 필드 업데이트
strcpy( rFpir.szPackageFileName, m_strCurrentNewPackageFileName );
DWORD dwPackageSize = GetFileSize( m_strDestFilePath+m_strCurrentNewPackageFileName+".zip" );
// 패키지 최대 사이즈를 넘어갔을 경우 or 단독패키지화 해야 할 파일(Client.exe 같은) 일 경우
bool bSoleFile = IsSoleFileWithSubDir( rFpir.szFileName );
if( dwPackageSize > m_dwPackageMaxSize || bSoleFile )
{
m_ZipArc.Open( m_strDestFilePath+m_strCurrentNewPackageFileName+".zip", CZipArchive::zipOpen );
if( 1 == m_ZipArc.GetCount( true ) )
{
// 파일이 하나뿐일경우 어쩔수 없으므로 패스
m_ZipArc.Close();
}
else
{
// 파일이 여러개일 경우, 마지막으로 추가된 파일 삭제
int nIdx = m_ZipArc.FindFile( rFpir.szFileName, CZipArchive::ffCaseSens, false );
m_ZipArc.DeleteFile( nIdx );
m_ZipArc.Close();
// ...한 다음, 다음 패키지 파일을 생성해 거기에 냅다 추가
m_strCurrentNewPackageFileName = GetNextPackageFileName();
m_ZipArc.Open( m_strDestFilePath+m_strCurrentNewPackageFileName+".zip", CZipArchive::zipCreate );
m_ZipArc.SetRootPath( m_strLocalFilePath );
CZipAddNewFileInfo zanfi( m_strLocalFilePath+rFpir.szFileName, false );
zanfi.Defaults();
m_ZipArc.AddNewFile( zanfi );
m_ZipArc.Close();
// patchinfo 에 기록될 패키지 이름 필드 업데이트
strcpy( rFpir.szPackageFileName, m_strCurrentNewPackageFileName );
}
// 단독패키지화 해야 할 파일의 경우 이후에 추가되는 파일이 없어야한다.
// (current패키지 이름을 비움 -> 다음 턴에 새 파일을 만들게됨)
if( bSoleFile )
{
/*
m_strCurrentNewPackageFileName = GetNextPackageFileName();
m_ZipArc.Open( m_strDestFilePath+m_strCurrentNewPackageFileName+".zip", CZipArchive::zipCreate );
m_ZipArc.SetRootPath( m_strLocalFilePath );
m_ZipArc.Close();
*/
m_strCurrentNewPackageFileName = "";
}
}
//strcpy( rFpir.szPackageFileName, m_strCurrentNewPackageFileName );
}
else
{
// 기존패키지 업데이트(replace file)
m_ZipArc.Open( m_strDestFilePath+rFpir.szPackageFileName+".zip", CZipArchive::zipOpen );
int nIdx = m_ZipArc.FindFile( rFpir.szFileName, CZipArchive::ffCaseSens, false );
if( -1 == nIdx )
{
CString strErr;
strErr.Format( "%s 패키지 파일 내에 %s 파일이 존재하지 않구마이", rFpir.szPackageFileName, rFpir.szFileName );
AfxMessageBox( strErr );
}
else
{
m_ZipArc.DeleteFile( nIdx );
}
m_ZipArc.SetRootPath( m_strLocalFilePath );
CZipAddNewFileInfo zanfi( m_strLocalFilePath+rFpir.szFileName, false );
zanfi.Defaults();
m_ZipArc.AddNewFile( zanfi );
m_ZipArc.Close( CZipArchive::afNoException, true );
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// PatchInfo 파일 저장&압축
bool CPatchMaker::UpdatePatchInfo()
{
// PatchInfo 저장
m_LocalPatchInfo.SetVersion( m_dwUpdateVersion );
m_LocalPatchInfo.Save( m_strDestFilePath+"PatchInfoV2" );
// PatchInfo 압축후 원본파일 삭제
CZipArchive zipArc;
zipArc.Open( m_strDestFilePath+"PatchInfoV2.zip", CZipArchive::zipCreate );
zipArc.AddNewFile( m_strDestFilePath+"PatchInfoV2", "PatchInfoV2" );
zipArc.Close();
DeleteFile( m_strDestFilePath+"PatchInfoV2");
// CInternetSession isess;
// CFtpConnection* pFtp = isess.GetFtpConnection( "211.233.42.245", "ryl", "fldjzk!$", 21, m_bPassiveMode );
// pFtp->SetCurrentDirectory( m_strPackageFilePath );
// pFtp->GetFile( "PatchInfo.zip", m_strDestFilePath+"PatchInfo.zip" );
// pFtp->Close();
// isess.Close();
return true;
}
//////////////////////////////////////////////////////////////////////////
//
// 새 패키지 파일 이름 생성
// (파일 이름 중 확장자 제외)
const char* CPatchMaker::GetNextPackageFileName()
{
static char szBuff[MAX_PACKAGE_FILE_NAME_LENGTH*2];
CTime t = CTime::GetCurrentTime();
CString strHeader = t.Format( "%Y%m%d_%H%M_" );
int n = 0;
char szTmp[4];
while( n < 1000 )
{
sprintf( szTmp, "%03d", n );
CString strFileName = m_strDestFilePath + strHeader + szTmp + ".zip";
// if( 0xFFFFFFFF == GetFileAttributes( strFileName ) )
// {
// if( ERROR_FILE_NOT_FOUND == GetLastError() )
// {
// strcpy( szBuff, strHeader+szTmp );
// break;
// }
// }
if( !IsFileExist( strFileName ) )
{
strcpy( szBuff, strHeader+szTmp );
break;
}
++n;
}
if( 1000 == n )
{
return NULL;
}
return szBuff;
}
bool CPatchMaker::IsExcludedFile( const char* szFileName )
{
for( int i = 0; i < m_astrFileNameExclusionList.GetSize(); ++i )
{
if( 0 == stricmp( szFileName, m_astrFileNameExclusionList[i] ) )
{
return true;
}
}
// hard-coded exclusion list
if( 0 == stricmp( szFileName, "." ) ) return true;
if( 0 == stricmp( szFileName, ".." ) ) return true;
if( 0 == stricmp( szFileName, "vssver.scc" ) ) return true;
return false;
}
bool CPatchMaker::IsExcludedFileWithSubDir( const char* szFileNameWithSubDir )
{
for( int i = 0; i < m_astrFileNameWithSubDirExclusionList.GetSize(); ++i )
{
if( 0 == stricmp( szFileNameWithSubDir, m_astrFileNameWithSubDirExclusionList[i] ) )
{
return true;
}
}
// hard-coded exclusion list
if( 0 == stricmp( szFileNameWithSubDir, "mp.ini" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "RenderOption.dat" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "ClientOption.dat" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Patchinfo.pat" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "UpdateFileList.txt" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "VersionInfo.dat" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Login.dat" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "LoginRes.dll" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Patchinfo.cache" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Patchinfo.local" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "LC2.OGG" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Z3D_SetupDirectX.exe" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "DirectXInstaller.exe" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "FileChecker.exe" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "DSETUP.dll" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "dsetup32.dll" ) ) return true;
return false;
}
bool CPatchMaker::IsExcludedSubDir( const char* szSubDir )
{
for( int i = 0; i < m_astrSubDirExclusionList.GetSize(); ++i )
{
if( 0 == stricmp( szSubDir, m_astrSubDirExclusionList[i] ) )
{
return true;
}
}
// hard-coded exclusion list
//if( 0 == stricmp( szSubDir, "GameGuard" ) ) return true;
if( !m_bCheckNoticeFolder && 0 == stricmp( szSubDir, "Notice" ) ) return true;
//if( 0 == stricmp( szSubDir, "update" ) ) return true;
if( 0 == stricmp( szSubDir, "DirectX" ) ) return true;
return false;
}
// 단일 패키지로 만들어야 하는 파일인가?
bool CPatchMaker::IsSoleFileWithSubDir( const char* szFileNameWithSubDir )
{
// for( int i = 0; i < m_astrSubDirSoleFileList.GetSize(); ++i )
// {
// if( 0 == stricmp( szSubDir, m_astrSubDirSoleFileList[i] ) )
// {
// return true;
// }
// }
// hard-coded sole file list
if( 0 == stricmp( szFileNameWithSubDir, "Client.exe" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Login.new" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "ItemScript.gsf" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "MonsterProtoType.gsf" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "script1.gsf" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "SkillScript.gsf" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "npcscript.mcf" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "quest.mcf" ) ) return true;
if( 0 == stricmp( szFileNameWithSubDir, "Script.mcf" ) ) return true;
// if( 0 == stricmp( szSubDir, "" ) ) return true;
return false;
}
int CPatchMaker::GetPatchInfoVersion()
{
if( false == LoadServerPatchInfoList() )
{
return -1;
}
return (int)m_ServerPatchInfo.GetVersion();
}