📄 gamedataset.cpp
字号:
#include <windows.h>
#include "mydatafile.H"
#include "basefunc.H"
#include "gamedataset.H"
// gobal
CGameDataSet g_objGameDataSet;
// const
const char szCOMMONANI[] ="ani/Common.ani";
const int _MAX_ACTNAME =32;
const int _MEM_CHECK_TIMER = 2000;
const int _LOW_MEM = 4*1024*1024;
const int _HIGH_MEM = 20*1024*1024;
const int _HIGHEST_DEADLINE = 30000;
const int _LOWEST_DEADLINE = 3000;
const int _3DOBJ_DEADLINE = 30*1000;
/*const int _3DMOTION_DEADLINE = 10*1000;
const int _3DTEXTURE_DEADLINE = 10*1000;
const int _3DEFFECT_DEADLINE = 10*1000;
*/
// globle....
DWORD g_dwDeadLine = 10000;
// local...
CRITICAL_SECTION csReadThread;
DEQUE_ANI dequeDataToLoad;
HANDLE hExitEvent =NULL; // exit event, set if u want terminate read process
HANDLE hReadEvent =NULL; // read event, for process read data
HANDLE hReadThread =NULL;
#ifdef _ANALYSIS_ON
DWORD g_dw3DObj=0, g_dw3DMotion=0, g_dw3DWMotion=0, g_dwTexture=0, g_dw3DEffect=0, g_dwDataAni=0;
#endif
//--------------------------------------------------------------
void AddReadDeque(CAni* pAni, int nExigence)
{
if (!pAni)
return;
::EnterCriticalSection(&csReadThread);
//------------------------------
if(nExigence == EXIGENCE_NORMAL)
dequeDataToLoad.push_back(pAni);
else
dequeDataToLoad.push_front(pAni);
//------------------------------
::LeaveCriticalSection(&csReadThread);
// come on, load my data now!
::SetEvent(hReadEvent);
}
//--------------------------------------------------------------
void UpPriority(CAni* pAni)
{
if (!pAni)
return;
::EnterCriticalSection(&csReadThread);
//------------------------------
if (pAni->GetStatus() == ANISTATUS_INIT)
{
int nAmount = dequeDataToLoad.size();
for (int i=nAmount-1; i>0; i--) // i>0
{
CAni* pTheAni = dequeDataToLoad[i];
if (pTheAni == pAni)
{
dequeDataToLoad.erase(dequeDataToLoad.begin()+i);
dequeDataToLoad.push_front(pAni);
break;
}
}
}
//------------------------------
::LeaveCriticalSection(&csReadThread);
}
//--------------------------------------------------------------
// Name: DataReadThread
//
// Note: read thread process function
//
// In: none
//
// Return: DWORD type, always 0.
//--------------------------------------------------------------
DWORD WINAPI DataReadThread(LPVOID lpThreadParameter)
{
HANDLE eventHandles[2];
eventHandles[0] =hReadEvent;
eventHandles[1] =hExitEvent;
// loop waiting for player events. If the exit event is signaled
// the thread will exit
while (WaitForMultipleObjects(2, eventHandles, FALSE, INFINITE)==WAIT_OBJECT_0)
{
while(!dequeDataToLoad.empty())
{
CAni* pAni = NULL;
try {
::EnterCriticalSection(&csReadThread);
//------------------------------
pAni = dequeDataToLoad.front();
dequeDataToLoad.pop_front();
pAni->SetStatus(ANISTATUS_LOADING);
//------------------------------
::LeaveCriticalSection(&csReadThread);
// loading.... cost lot's of time
pAni->Load();
}
catch(...)
{
::LogMsg("catch error in data load thread.");
CDynamicAni* pDynaAni = (CDynamicAni*) (pAni);
if (pDynaAni)
::LogMsg("crashed when loading %s :%s", pDynaAni->m_szIniFile, pDynaAni->m_szIndex);
else
::LogMsg("can't dynamic_cast the ani pointer");
}
}
}
return 0;
}
//--------------------------------------------------------------
BOOL DataReadThreadInit(void)
{
hReadEvent =CreateEvent (NULL, // no security
FALSE, // auto reset
FALSE, // initial event reset
NULL); // no name
if (!hReadEvent)
return false;
hExitEvent =CreateEvent (NULL, // no security
FALSE, // auto reset
FALSE, // initial event reset
NULL); // no name
if (!hExitEvent)
return false;
//---------------------------------
dequeDataToLoad.clear();
//---------------------------------
DWORD dwIdThread;
hReadThread =CreateThread(NULL, // default security
0, // default stack size
DataReadThread, // pointer to thread routine
NULL, // argument for thread
0, // start it right away
&dwIdThread);
if(!hReadThread)
return false;
SetThreadPriority(hReadThread, g_objGameDataSet.m_dwReadThreadPriority);
return true;
}
//--------------------------------------------------------------
void DataReadThreadDestroy(void)
{
while (true)
{
if (dequeDataToLoad.size() <= 0)
break;
Sleep(50);
}
if(hReadThread)
{
SetEvent(hExitEvent);
Sleep(100); // waiting for thread exit
CloseHandle(hReadThread);
hReadThread =NULL;
}
if(hReadEvent)
{
CloseHandle(hReadEvent);
hReadEvent =NULL;
}
if(hExitEvent)
{
CloseHandle(hExitEvent);
hExitEvent =NULL;
}
}
//--------------------------------------------------------------
// CGameDataSet
//--------------------------------------------------------------
CGameDataSet::CGameDataSet(void)
{
}
CGameDataSet::~CGameDataSet(void)
{
this->Destroy();
//------------------------------------
::DeleteCriticalSection(&csReadThread);
extern CRITICAL_SECTION sAniCritical;
::DeleteCriticalSection(&sAniCritical);
}
//--------------------------------------------------------------
void CGameDataSet::Init(void)
{
DWORD m_dw3DMotionLife = 30*1000;
DWORD m_dw3DTextureLife = 30*1000;
DWORD m_dw3DEffectLife = 30*1000;
DWORD m_dwPuzzleLife = 30*1000;
DWORD m_dwPuzzlePreloadSize = 1;
DWORD m_dwReadThreadPriority = THREAD_PRIORITY_NORMAL;
this->InitSystemPolicy();
m_mapDataAni.clear();
m_set3DObj.clear();
m_set3DMotion.clear();
m_set3DWeaponMotion.clear();
m_set3DMantleMotion.clear();
m_set3DMountMotion.clear();
m_set3DTexture.clear();
m_set3DEffect.clear();
m_setEmotion.clear ();
this->LoadRes("ini/3dobj.ini", m_mapResMesh);
this->LoadRes("ini/3dtexture.ini", m_mapResTexture);
this->LoadRes("ini/3dmotion.ini", m_mapResMotion);
this->LoadRes("ini/3deffectobj.ini", m_mapResEffectObj);
this->LoadRes("ini/weaponmotion.ini", m_mapResWeaponMotion);
this->LoadRes("ini/mantlemotion.ini", m_mapResMantleMotion);
this->LoadRes("ini/mountmotion.ini", m_mapResMountMotion);
this->LoadRes("ini/sound.ini", m_mapSound);
this->CreateItemEffectInfo();
::InitializeCriticalSection(&csReadThread);
extern CRITICAL_SECTION sAniCritical;
::InitializeCriticalSection(&sAniCritical);
if (!::DataReadThreadInit())
::ErrorOut("动态数据读入线程初始化错误!");
m_timerCheck = ::TimeGet();
g_dwDeadLine = 10000;
// open pack data file
this->InitDnp();
m_objStrRes.Init();
this->CreateEmotionInfo ();
}
//--------------------------------------------------------------
void CGameDataSet::InitSystemPolicy(void)
{
// get total memory
MEMORYSTATUS stat;
::GlobalMemoryStatus(&stat);
char szTitle[64];
if(stat.dwTotalPhys >= 400*1000*1000)
strcpy(szTitle, "MEM512");
else if(stat.dwTotalPhys >= 192*1000*1000)
strcpy(szTitle, "MEM256");
else
strcpy(szTitle, "MEM128");
const char szCommon[] = "ini/common.ini";
char szSubtitle[128];
int nData;
strcpy(szSubtitle, "3DMotionLife");
if(::IniDataGet(szCommon, szTitle, szSubtitle, nData))
m_dw3DMotionLife = nData;
strcpy(szSubtitle, "3DTextureLife");
if(::IniDataGet(szCommon, szTitle, szSubtitle, nData))
m_dw3DTextureLife = nData;
strcpy(szSubtitle, "3DEffectLife");
if(::IniDataGet(szCommon, szTitle, szSubtitle, nData))
m_dw3DEffectLife = nData;
strcpy(szSubtitle, "PuzzleLife");
if(::IniDataGet(szCommon, szTitle, szSubtitle, nData))
m_dwPuzzleLife = nData;
strcpy(szSubtitle, "PuzzlePreloadSize");
if(::IniDataGet(szCommon, szTitle, szSubtitle, nData))
m_dwPuzzlePreloadSize = nData;
strcpy(szSubtitle, "ReadThreadPriority");
if(::IniDataGet(szCommon, szTitle, szSubtitle, nData))
{
switch(nData)
{
case -1:
m_dwReadThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
break;
case 0:
m_dwReadThreadPriority = THREAD_PRIORITY_NORMAL;
break;
case 1:
m_dwReadThreadPriority = THREAD_PRIORITY_ABOVE_NORMAL;
break;
default:
m_dwReadThreadPriority = THREAD_PRIORITY_NORMAL;
break;
}
}
}
//--------------------------------------------------------------
void CGameDataSet::Destroy (void)
{
// got anyting to load by loading thread?
::DataReadThreadDestroy();
// free pack data file
::MyDataFileClose();
this->DestroyDataAni();
this->Destroy3DMotion();
this->Destroy3DObj();
this->Destroy3DTexture();
this->Destroy3DEffect();
this->Destroy3DWeaponMotion();
this->Destroy3DMantleMotion();
this->DestroyItemEffectInfo();
// res
m_mapResMesh.clear();
m_mapResMotion.clear();
m_mapResTexture.clear();
m_mapResEffectObj.clear();
m_mapResWeaponMotion.clear();
m_mapResMantleMotion.clear();
m_objStrRes.Destroy();
m_mapSound.clear();
m_setEmotion.clear ();
// quit 3d device now
CMyBitmap::Quit3D();
SAFE_DELETE(CAni::s_pDai);
SAFE_DELETE(CAni::s_pFrameSet);
}
//--------------------------------------------------------------
void CGameDataSet::LoadRes(const char* pszResFile, MAP_RES& mapRes)
{
if (!pszResFile)
return;
FILE* fp = fopen(pszResFile, "r");
if (!fp)
{
::ErrorOut("can't open file:%s!", pszResFile);
return;
}
mapRes.clear();
while(true)
{
char szLine[1024] = "";
if (EOF == fscanf(fp, "%s\n", szLine))
break;
OBJID id = ID_NONE;
char szFile[256] = "";
if (2 == sscanf(szLine, "%u=%s", &id, szFile))
{
string strFile = szFile;
mapRes[id] = strFile;
}
}
fclose(fp);
}
//--------------------------------------------------------------
void CGameDataSet::Process(void)
{
this->ProcessDataAni();
this->Process3DMotionSet();
this->Process3DWeaponMotionSet();
this->Process3DMantalMotionSet();
//this->Process3DObjSet();
this->Process3DTextureSet();
this->Process3DEffectSet();
}
DWORD g_dwEgLoad = 0, g_dwImLoad = 0, g_dwNmLoad = 0;
//--------------------------------------------------------------
//--------------------------------------------------------------
CAni* CGameDataSet::GetDataAni (const char* pszFileName, const char* pszTitle, int nExigence, DWORD dwLife)
{
// check ...
if((!pszFileName || strlen(pszFileName) < 1) || (!pszTitle || strlen(pszTitle) < 1) )
return NULL;
// CreateID
static char szTemp[256];
strcpy(szTemp, pszFileName);
strcat((char*)szTemp, pszTitle);
extern DWORD Str2ID( const char* str );
OBJID idAni = Str2ID(szTemp);
// search ...
MAP_DYNAMICANI::iterator iter = m_mapDataAni.find(idAni);
if(iter != m_mapDataAni.end())
{
CDynamicAni* pDAni = iter->second;
if (pDAni)
{
// found it!
switch (pDAni->GetStatus())
{
case ANISTATUS_INIT:
case ANISTATUS_LOADING:
{
if (nExigence == EXIGENCE_IMMEDIATE)
{
g_dwEgLoad ++;
// still waiting load?
if (ANISTATUS_INIT == pDAni->GetStatus())
::UpPriority(pDAni);
// we must waiting the accomplish of data loading
DWORD timeBegin = ::TimeGet();
while (ANISTATUS_INIT == pDAni->GetStatus()
|| ANISTATUS_LOADING == pDAni->GetStatus())
{
::Sleep(30);
if (::TimeGet() >= timeBegin+3000)
{
::LogMsg("Error: can't complete ani loading in 3 sec. ani(%s :%s)", pDAni->m_szIniFile, pDAni->m_szIndex);
timeBegin = ::TimeGet();
}
}
// loading complished
if (ANISTATUS_LOADED == pDAni->GetStatus())
{
pDAni->ResetLife();
return pDAni;
}
else
{
return NULL;
}
}
else
return NULL;
}
break;
case ANISTATUS_LOADED:
{
pDAni->ResetLife();
return pDAni;
}
break;
case ANISTATUS_FAILED:
{
#ifdef _DEBUG
// ::ErrorOut("ERROR: hahaha Ani:[%s] of [%s] load failed", pszTitle, pszFileName);
#endif
m_mapDataAni.erase(iter);
SAFE_DELETE (pDAni);
return NULL;
}
break;
default:
{
::ErrorOut("ERROR: Ani:[%s] of [%s] got invalid status:%u CGameDataSet::GetDataAni()", pszTitle, pszFileName, pDAni->GetStatus());
m_mapDataAni.erase(iter);
SAFE_DELETE (pDAni);
return NULL;
}
break;
}
}
else
{
::LogMsg("Error: found invalid data ani in CGameDataSet::GetDataAni()");
m_mapDataAni.erase(iter);
}
}
// ani data not found, so we must create new one...
//CAni::s_setAniFile.AddAniFile((char*)pszFileName);
CAni::s_pDai->Load(pszFileName, true);
CDynamicAni* pNewDAni = new CDynamicAni(pszFileName, pszTitle);
if (!pNewDAni)
return NULL;
pNewDAni->SetLife(dwLife);
if (EXIGENCE_IMMEDIATE == nExigence)
{
g_dwImLoad ++;
if (pNewDAni->Load() && ANISTATUS_LOADED == pNewDAni->GetStatus())
{
m_mapDataAni[pNewDAni->m_idAni] = pNewDAni;
return pNewDAni;
}
else
{
#ifdef _DEBUG
::ErrorOut("ERROR: Ani:[%s] not found in [%s]", pszTitle, pszFileName);
#endif
// Test if the resource is the second resource
if ( strcmp ( pszFileName, "ani/Control2.Ani" ) == 0 )
::PostCmd(CMD_RESOURCE_LOSE) ;
SAFE_DELETE (pNewDAni) ;
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -