Files
git 9cb257e7ae Add GameClients drops and keep current 1602 source work.
CN1602 is the local client. KR is the official tree with unpacked Data, System, and Sound. Packed .wpk files stay off git.
2026-08-30 23:24:31 +03:00

454 lines
13 KiB
C++

#include "StdAfx.h"
#include ".\sharedfieldinfo.h"
#include <io.h>
#include <fstream>
#include <ProgramCommon/WzArchive.h>
#include <3DEngine/Common/IncludeAll_NewWorld.h>
#include <3DEngine/3DTerrain/WorldBase.h>
#include <ProgramCommon/DiscAccess.h>
#include "GameServerEx.h"
#include <MapInfoParser.h>
#include "AppliedNpcDependencyChain.h"
SharedFieldInfo::SharedFieldInfo(void)
: m_pWorldBase(NULL)
, m_LastUsedRoomIndex(0)
{
// (f100623.1L) cache for checksums
ZeroMemory(&checksums_, sizeof(checksums_));
}
SharedFieldInfo::~SharedFieldInfo(void)
{
Destroy();
}
BOOL SharedFieldInfo::Create( FIELDCODE fieldcode, const char * field_path, FIELDCODE wmocode, BOOL bNewPathEngine, BOOL bWarCastle )
{
if (field_path == NULL || field_path[0] == '\0')
{
SUNLOG(eCRITICAL_LOG, "[SharedFieldInfo::Create] empty path, FieldCode=%u WMO=%u",
(unsigned)fieldcode, (unsigned)wmocode);
return FALSE;
}
if (g_pGameServer == NULL || g_pGameServer->m_fnContactTerrain == NULL)
{
SUNLOG(eCRITICAL_LOG, "[SharedFieldInfo::Create] terrain DLL is not ready");
return FALSE;
}
m_Code = fieldcode;
m_WMOCode = wmocode;
m_bNewPathEngine = bNewPathEngine;
m_bWarCastle = bWarCastle;
_tcsncpy( m_tszMapPath, field_path, MAX_PATH );
m_tszMapPath[MAX_PATH] = '\0';
m_MapObjectInfoHash.clear();
ASSERT(!m_pWorldBase);
m_pWorldBase = (CWorldBase *)g_pGameServer->m_fnContactTerrain( CT_NEW_WORLD, 0 );
if (m_pWorldBase == NULL)
{
SUNLOG(eCRITICAL_LOG, "[SharedFieldInfo::Create] CT_NEW_WORLD failed, FieldCode=%u",
(unsigned)fieldcode);
return FALSE;
}
if( m_bNewPathEngine )
m_pWorldBase->Create();
else
m_pWorldBase->Create( FALSE );
// (CHANGES) (f100501.2L) (WAVERIX) add the debugging facility
SUNLOG(eDEV_LOG, _T("|Start Read|FieldCode=%d|WMOCode=%d|Path=%s|"),
fieldcode, wmocode, field_path);
if (_Load(field_path) == false)
{
SUNLOG(eCRITICAL_LOG, _T("|Reading failed!|Path=%s|"), field_path);
Destroy();
return false;
}
SUNLOG(eDEV_LOG, _T("|End Read|Path=%s|"), field_path);
_SetStartingTileIndex();
_SetCRStartingTileIndex();
if( m_StartTiles.size() == 0 && m_CR1StartTiles.size() == 0 && m_CR2StartTiles.size() == 0 )
{
SUNLOG( eDEV_LOG, "[SharedFieldInfo::Create] StartTiles not found, FieldCode = %u, FieldPath = %s", fieldcode, field_path );
}
#ifdef _DEV_TAIYO_PATHENGINE_CODE
//LARGE_INTEGER firstcounter,nextcounter;
//QueryPerformanceCounter(&firstcounter);
//if( m_bNewPathEngine )
//{
// char pszFilePath[_MAX_PATH]={0,};
// char pszFileName[_MAX_FNAME]={0,};
// char pszDir[_MAX_PATH]={0,};
// _splitpath( field_path, NULL, pszDir, pszFileName, NULL );
// _snprintf( pszFilePath, _MAX_PATH, "%s\\%s.pfc", pszDir, pszFileName );
// m_pWorldBase->x_pPathFinder->GenerateCollisionPreprocess( m_pWorldBase->GetDiscAccess(), pszFilePath );
//}
//else
// m_pWorldBase->x_pPathFinder->GenerateCollisionPreprocess( NULL, NULL );
//QueryPerformanceCounter(&nextcounter);
//__int64 elapsedclock = nextcounter.QuadPart - firstcounter.QuadPart;
//__int64 elapsedmillsecond = elapsedclock / g_pGameServer->m_freq.QuadPart;
//printf( "[GenerateCollisionPreprocess] FieldCode[%d] Tick[%I64d]\n", m_Code, elapsedmillsecond );
#endif
return TRUE;
}
VOID SharedFieldInfo::Destroy()
{
_UnloadMapObjectInfo();
m_TriggerInfoManager.Release();
if( m_pWorldBase )
{
m_pWorldBase->Destroy( NULL );
g_pGameServer->m_fnContactTerrain( CT_DELETE_WORLD, m_pWorldBase );
m_pWorldBase = NULL;
}
m_MapObjectInfoHash.clear();
}
VOID SharedFieldInfo::_UnloadMapObjectInfo()
{
MAPOBJECT_INFO * pDelNode = NULL;
MAPOBJECT_INFO_HASH_IT itend = m_MapObjectInfoHash.end();
for( MAPOBJECT_INFO_HASH_IT it = m_MapObjectInfoHash.begin(); it != itend ; ++it )
{
pDelNode = it->second;
SAFE_DELETE( pDelNode );
}
m_MapObjectInfoHash.clear();
}
VOID SharedFieldInfo::_SetStartingTileIndex()
{
m_StartTiles.clear();
for( int i = '0' ; i <= '9' ; ++i )
{
WzSpecialArea * pArea = m_pWorldBase->GetSpecialArea( CharToWzID('S','T','R',i) );
if( !pArea ) continue;
ASSERT( pArea->m_wbvRegion.m_eBvType == BVT_PATH_TILE_INDEX );
if( pArea->m_wbvRegion.m_eBvType != BVT_PATH_TILE_INDEX )
continue;
ASSERT( pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount != 0 );
for( DWORD j = 0 ; j < pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount ; ++j )
m_StartTiles.push_back( pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[j] );
}
for( int i = 'A' ; i <= 'Z' ; ++i )
{
WzSpecialArea * pArea = m_pWorldBase->GetSpecialArea( CharToWzID('S','T','R', i) );
if( !pArea ) continue;
ASSERT( pArea->m_wbvRegion.m_eBvType == BVT_PATH_TILE_INDEX );
if( pArea->m_wbvRegion.m_eBvType != BVT_PATH_TILE_INDEX )
continue;
ASSERT( pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount != 0 );
for( DWORD j = 0 ; j < pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount ; ++j )
m_StartTiles.push_back( pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[j] );
}
}
VOID SharedFieldInfo::_SetCRStartingTileIndex()
{
m_CR1StartTiles.clear();
m_CR2StartTiles.clear();
for( int i = '0' ; i <= '9' ; ++i )
{
WzSpecialArea * pArea = m_pWorldBase->GetSpecialArea( CharToWzID('C','R','1',i) );
if( !pArea ) continue;
ASSERT( pArea->m_wbvRegion.m_eBvType == BVT_PATH_TILE_INDEX );
if( pArea->m_wbvRegion.m_eBvType != BVT_PATH_TILE_INDEX )
continue;
ASSERT( pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount != 0 );
for( DWORD j = 0 ; j < pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount ; ++j )
m_CR1StartTiles.push_back( pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[j] );
pArea = m_pWorldBase->GetSpecialArea( CharToWzID('C','R','2',i) );
if( !pArea ) continue;
ASSERT( pArea->m_wbvRegion.m_eBvType == BVT_PATH_TILE_INDEX );
if( pArea->m_wbvRegion.m_eBvType != BVT_PATH_TILE_INDEX )
continue;
ASSERT( pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount != 0 );
for( DWORD j = 0 ; j < pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount ; ++j )
m_CR2StartTiles.push_back( pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[j] );
}
}
BOOL SharedFieldInfo::_Load( const char * field_path )
{
CWzArchive archive;
CDiscAccess cda;
cda.Create();
// (WAVERIX) (090718) (CHANGES) Sun3DEngine_090717 version???? ?¥å?? DiscAccess ???? ??? ?¥ê? ????.
m_pWorldBase->SetDiscAccess(&cda);
if( _access(field_path,0) == -1 )
{
SUNLOG( eCRITICAL_LOG, "[FieldInfo::Load] Failed : %s file is not Exist", field_path );
return FALSE;
}
if( archive.LoadFile( const_cast<char *>(field_path) ) == FALSE )
{
SUNLOG( eCRITICAL_LOG, "[FieldInfo::Load] Failed LoadFile() : From Fieldxx.map[%s]", field_path );
archive.Close();
return FALSE;
}
// (f100623.1L)
ZeroMemory(&checksums_, sizeof(checksums_));
archive.Seek( 4, SO_CURRENT );
archive >> m_Version;
archive.Seek( -6, SO_CURRENT );
if( m_pWorldBase->Serialize( &archive ) == FALSE )
{
SUNLOG( eCRITICAL_LOG, "[FieldInfo::Load] Failed WorldBase_Serialize() : From Fieldxx.map[%s]", field_path );
archive.Close();
return FALSE;
}
// ???????? + ????? ????
if( !_Serialize_WMO( archive ) )
{
SUNLOG( eCRITICAL_LOG, "[FieldInfo::Load] Failed _Serialize_WMO() : From Fieldxx.map[%s]", field_path );
archive.Close();
return FALSE;
}
// release resources
archive.Close();
return true;
}
BOOL SharedFieldInfo::_Serialize_WMO( CWzArchive & archive )
{
BOOL bAreaChunk = FALSE;
while( TRUE )
{
St_ChunkInfo ci = archive.ReadChunk();
if( ci.m_nID == 0x1792 )
{
bAreaChunk = TRUE;
break;
}
archive.SkipCurrentChunk(ci);
}
ASSERT( TRUE == bAreaChunk );
char pszFilePath[_MAX_PATH]={0,};
char pszFileName[_MAX_FNAME]={0,};
char pszDir[_MAX_PATH]={0,};
const sWMOINFO * pInfo = MapInfoParser::Instance()->FindWMOInfo(GetWMOCode());
if( !pInfo ) return FALSE;
#ifdef _HARDMODE_TRIGGER_PRINT_
;{
std::ofstream out_trigger("TRIGGER.txt", std::ios::app);
CHAR buffer[512] = { 0, };
sprintf(buffer, "mapcode : [%d] filename : [%s]\n", pInfo->Code, pInfo->pszPath);
out_trigger << buffer;
};
#endif //_HARDMODE_TRIGGER_PRINT_
return _LoadMapObjectInfo(pInfo->pszPath);
}
BOOL SharedFieldInfo::_LoadMapObjectInfo( const char * pszFilePath )
{
_tcsncpy( m_tszWmoPath, pszFilePath, MAX_PATH );
m_tszWmoPath[MAX_PATH-1] = '\0';
CWzArchive l_archive;
l_archive.SetDiscAccess(GetWorldBase()->GetDiscAccess());
if( _access(pszFilePath,0) == -1 )
{
SUNLOG( eCRITICAL_LOG, "[_LoadMapObjectInfo] Failed : %s file is not Exist", pszFilePath );
return FALSE;
}
if(!l_archive.LoadFile( const_cast<char*>(pszFilePath) ))
{
return FALSE;
}
WORD wVersion = 0;
l_archive.Seek( 4, SO_CURRENT );
l_archive >> wVersion;
l_archive.SetVersion( wVersion );
St_LHFileHeader fhInfo = { 0, };
if( 170 < l_archive.GetVersion() )
{
l_archive.Read(&fhInfo.wSecondVersion, sizeof(WORD));
l_archive.Read(&fhInfo.dwCheckSum, sizeof(DWORD));
SUNLOG( eDEV_LOG, "Second Ver[%u] and CheckSum[%u]", fhInfo.wSecondVersion, fhInfo.dwCheckSum );
}
// (f100623.1L)
checksums_.checksum_map = m_pWorldBase->GetCheckSum();
checksums_.checksum_wmo = fhInfo.dwCheckSum;
GetWorldBase()->SerializeExtraAreaInfo(&l_archive, TRUE);
_SerializeMapObjectAll(l_archive);
// Map?? Wmo ?????? Version ???? ??!
_CheckVersionBetweenMapWmo( GetVersion(), l_archive.GetVersion() );
l_archive.Close();
return TRUE;
}
VOID SharedFieldInfo::_SerializeMapObjectAll( CWzArchive & archive )
{
CLoadHelper * pLoadHelper = GetWorldBase()->x_pLoadHelper;
pLoadHelper->LoadObj(&archive);
//???? ??? ????? ?¥å?
int count = pLoadHelper->GetObjectCount();
St_LHObject * pLHObject = pLoadHelper->GetObject();
//ASSERT( count < (ITEM_OBJECT_KEY - MAP_OBJECT_KEY) ); //< ??? 5???? ??????? ???.
for( int i = 0 ; i < count ; ++i )
{
MAPOBJECT_INFO * pObject = new MAPOBJECT_INFO;
//__NA001283_20090303_COLLECTION_MAPOBJECTID
pObject->dwMapObjectID = i + MAP_OBJECT_KEY;
pObject->wzId = pLHObject[i].m_WzID;
pObject->wvPos = pLHObject[i].m_wvPos;
pObject->wzRot = pLHObject[i].m_wvRot;
pObject->wzScale = pLHObject[i].m_wvScale;
pObject->wzBV = pLHObject[i].m_wzBV;
pObject->dwAttribute = pLHObject[i].m_dwAttribute;
pObject->CollectionID = pLHObject[i].m_wiUser; // ???? ????? -> user == ????? (????? ?¥å???)
// ??? ?????? ????
pObject->dwExtraInfos[eMAPOBJECT_TYPE] = pLHObject[i].m_dwParam[eMAPOBJECT_TYPE];
pObject->dwExtraInfos[eMAPOBJECT_MONSTER] = pLHObject[i].m_dwParam[eMAPOBJECT_MONSTER];
pObject->dwExtraInfos[eMAPOBJECT_USE_ALPHA] = pLHObject[i].m_dwParam[eMAPOBJECT_USE_ALPHA];
pObject->dwExtraInfos[eMAPOBJECT_LINKED_MONSTER_REGEN_TYPE] =
pLHObject[i].m_dwParam[eMAPOBJECT_LINKED_MONSTER_REGEN_TYPE];
ASSERT( NULL == FindMapObjectInfo( pObject->dwMapObjectID ) );
m_MapObjectInfoHash.insert( MAPOBJECT_INFO_PAIR(pObject->dwMapObjectID, pObject) );
}
pLoadHelper->DeleteObject();
// ????? ???? ?¥å?
m_TriggerInfoManager.LoadGroupInfos( archive, AppliedNpcDependencyChain::Instance()->GetIEventRegisterForNpcKillByTrigger() );
}
BOOL SharedFieldInfo::_LoadPathEngineCollision( char * pszFileName )
{
CWzArchive l_archive;
l_archive.SetDiscAccess(GetWorldBase()->GetDiscAccess());
if( _access(pszFileName,0) == -1 )
{
SUNLOG( eCRITICAL_LOG, "[_LoadPathEngineCollision] Failed : %s file is not Exist", pszFileName );
return FALSE;
}
if( !l_archive.LoadFile( pszFileName ) )
return FALSE;
l_archive.Seek( 4, SO_CURRENT );
WORD wVersion = 0;
l_archive >> wVersion;
wVersion = VERSION_WEBZEN_MAP;
l_archive.SetVersion(wVersion);
CWzArray<WzVector> wzArrayVect;
int iObjCnt = 0;
int iBvCnt = 0;
int iVCnt = 0;
int iID = 0;
WzVector wvPos;
//. Object ?????? ????? ???
l_archive >> iObjCnt;
for(int iCnt=0;iCnt<iObjCnt;++iCnt)
{
l_archive >> iBvCnt;
if( iBvCnt )
{
l_archive >> iVCnt;
l_archive >> iID;
l_archive >> wvPos;
l_archive.Read(wzArrayVect.GetBufferPtr(),iVCnt*sizeof(WzVector));
GetWorldBase()->x_pPathFinder->EntryCollisionTerritoryUnderLine(ECO_OBJECT,iID,wvPos,iVCnt,wzArrayVect.GetBufferPtr());
}
}
//. SpeedTree ?????? ????? ???
l_archive >> iObjCnt;
for(int iCnt=0;iCnt<iObjCnt;++iCnt)
{
l_archive >> iVCnt;
if( iVCnt )
{
l_archive >> iID;
l_archive >> wvPos;
l_archive.Read(wzArrayVect.GetBufferPtr(),iVCnt*sizeof(WzVector));
GetWorldBase()->x_pPathFinder->EntryCollisionTerritoryUnderLine(ECO_SPEEDTREE,iID,wvPos,iVCnt,wzArrayVect.GetBufferPtr());
}
}
l_archive.Close();
return TRUE;
}
VOID SharedFieldInfo::_CheckVersionBetweenMapWmo( DWORD MapVersion, DWORD WmoVersion )
{
// 167 ???? ?????? Map?? ???? ?????? ???? ?¥å??? ????? ????.
if( MapVersion <= 167 )
{
SUNLOG( eCRITICAL_LOG, "[_CheckVersionBetweenMapWmo] Warning! %s Version[%u] is Low!!", m_tszMapPath, MapVersion );
}
// 162, 166, 167?? ???? Wmo ???? Map?? ?????? ?? ?????? ????.
if( MapVersion > 162 && WmoVersion <= 162 ||
MapVersion > 166 && WmoVersion <= 166 ||
MapVersion > 167 && WmoVersion <= 167 ||
MapVersion > 170 && WmoVersion <= 170 )
{
SUNLOG( eCRITICAL_LOG, "[_CheckVersionBetweenMapWmo] Critical! %s Version[%u] is Low!!", m_tszMapPath, WmoVersion );
}
}