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>
780 lines
21 KiB
C++
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();
|
|
} |