187 lines
9.8 KiB
C++
187 lines
9.8 KiB
C++
|
||
#include "Stdafx.h"
|
||
#include "DNWaitUserManager.h"
|
||
#include "Log.h"
|
||
#include "DNExtManager.h"
|
||
#include "DNDivisionManager.h"
|
||
|
||
extern TMasterConfig g_Config;
|
||
CDNWaitUserManager * g_pWaitUserManager = NULL;
|
||
|
||
CDNWaitUserManager::CDNWaitUserManager()
|
||
{
|
||
m_nWorldMaxUser = 0;
|
||
m_nWorldCurUser = 0;
|
||
m_nWorldPreCurUser = 0;
|
||
}
|
||
|
||
CDNWaitUserManager::~CDNWaitUserManager()
|
||
{
|
||
}
|
||
|
||
bool CDNWaitUserManager::Initialize(int nMaxuser)
|
||
{
|
||
if (nMaxuser < 0)
|
||
{
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
m_nWorldMaxUser = g_pExtManager->GetWorldMaxUser(g_Config.nWorldSetID);
|
||
}
|
||
else
|
||
{
|
||
//강제세팅 부분
|
||
{
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
m_nWorldMaxUser = nMaxuser;
|
||
}
|
||
if (g_pDivisionManager)
|
||
UpdateCurCount(g_pDivisionManager->GetCurUserCount());
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void CDNWaitUserManager::UpdateCurCount(UINT nCurCount)
|
||
{
|
||
if (m_WaitUserList.empty()) return;
|
||
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
if (m_nWorldMaxUser > nCurCount || m_nWorldPreCurUser > nCurCount)
|
||
WaitUserProcessAsync(nCurCount);
|
||
m_nWorldPreCurUser = m_nWorldCurUser = nCurCount;
|
||
}
|
||
|
||
bool CDNWaitUserManager::IsWaitUser(UINT nAccountDBID)
|
||
{
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
|
||
std::list <_WAITUSER>::iterator ii;
|
||
for (ii = m_WaitUserList.begin(); ii != m_WaitUserList.end(); ii++)
|
||
if ((*ii).nAccountDBID == nAccountDBID)
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
int CDNWaitUserManager::AddWaitUser(int nServerID, UINT nAccountDBID, USHORT &nLeftTicketNum, USHORT &nLastEstimateCalcTime)
|
||
{
|
||
if (IsWaitUser(nAccountDBID))
|
||
{
|
||
g_Log.Log(LogType::_ERROR, g_Config.nWorldSetID, nAccountDBID, 0, 0, L"CDNWaitUserManager::AddWaitUser Fail AlreadyAdd\n");
|
||
return ERROR_GENERIC_UNKNOWNERROR;
|
||
}
|
||
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
|
||
_WAITUSER wait;
|
||
|
||
wait.nServerID = nServerID;
|
||
wait.nAccountDBID = nAccountDBID;
|
||
wait.nAddTimeTick = timeGetTime();
|
||
wait.nWaitTicketNum = (USHORT)m_WaitUserList.size()+1;
|
||
|
||
//현재 기준으로 예상시간을 계산해서 던저준다.
|
||
nLeftTicketNum = wait.nWaitTicketNum;
|
||
nLastEstimateCalcTime = CalcEstimateTime(nLeftTicketNum, m_nWorldCurUser);
|
||
|
||
m_WaitUserList.push_back(wait);
|
||
|
||
return ERROR_NONE;
|
||
}
|
||
|
||
void CDNWaitUserManager::DelWaitUser(int nServerID, UINT nAccountDBID)
|
||
{
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
|
||
USHORT nDelTicketNum = 0;
|
||
std::list <_WAITUSER>::iterator ii;
|
||
for (ii = m_WaitUserList.begin(); ii != m_WaitUserList.end(); ii++)
|
||
{
|
||
if ((*ii).nAccountDBID == nAccountDBID)
|
||
{
|
||
nDelTicketNum = (*ii).nWaitTicketNum;
|
||
m_WaitUserList.erase(ii);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (nDelTicketNum > 0)
|
||
{
|
||
//update ticketnum
|
||
for (ii = m_WaitUserList.begin(); ii != m_WaitUserList.end(); ii++)
|
||
{
|
||
if ((*ii).nWaitTicketNum > nDelTicketNum)
|
||
(*ii).nWaitTicketNum--;
|
||
}
|
||
UpdateProcessIndexAsync(nDelTicketNum, 1);
|
||
}
|
||
}
|
||
|
||
UINT CDNWaitUserManager::GetWaitUserCount()
|
||
{
|
||
ScopeLock <CSyncLock> sync(m_Sync);
|
||
return (UINT)m_WaitUserList.size();
|
||
}
|
||
|
||
USHORT CDNWaitUserManager::CalcEstimateTime(UINT nLeftWaitUser, UINT nWorldUserCount)
|
||
{
|
||
USHORT nEstimate = (USHORT)((((float)(1.0f / (((float)nWorldUserCount / 2.0f) / 60.0f)) * (float)nLeftWaitUser) * 2.8f) + 0.5f);
|
||
return nEstimate <= 0 ? 5 : nEstimate;
|
||
}
|
||
|
||
void CDNWaitUserManager::WaitUserProcessAsync(UINT nCurCnt)
|
||
{
|
||
int i, nProcessCnt = m_nWorldMaxUser - nCurCnt;
|
||
if (nProcessCnt <= 0) return;
|
||
|
||
std::vector <int> vServerList;
|
||
std::vector <std::pair<int, UINT>> vProcessList;
|
||
std::list <_WAITUSER>::iterator ii;
|
||
for (ii = m_WaitUserList.begin(), i = 0; ii != m_WaitUserList.end() && i < nProcessCnt;)
|
||
{
|
||
std::vector <int>::iterator ih = std::find(vServerList.begin(), vServerList.end(), (*ii).nServerID);
|
||
if (ih == vServerList.end()) vServerList.push_back((*ii).nServerID);
|
||
|
||
vProcessList.push_back(std::make_pair((*ii).nServerID, (*ii).nAccountDBID));
|
||
ii = m_WaitUserList.erase(ii);
|
||
i++;
|
||
if (i >= WAITPROCESSMAX) break;
|
||
}
|
||
|
||
MALOWaitUserProcess Process;
|
||
std::vector <std::pair<int, UINT>>::iterator iv;
|
||
//construct
|
||
for (i = 0; i < (int)vServerList.size(); i++)
|
||
{
|
||
memset(&Process, 0, sizeof(MALOWaitUserProcess));
|
||
Process.nCurCount = nCurCnt;
|
||
for (iv = vProcessList.begin(); iv != vProcessList.end(); iv++)
|
||
{
|
||
if ((*iv).first == vServerList[i])
|
||
{
|
||
Process.nAccountArr[Process.nCount] = (*iv).second;
|
||
Process.nCount++;
|
||
}
|
||
}
|
||
|
||
g_pDivisionManager->SendWaitProcess(vServerList[i], &Process);
|
||
}
|
||
|
||
for (ii = m_WaitUserList.begin(); ii != m_WaitUserList.end(); ii++)
|
||
(*ii).nWaitTicketNum = (*ii).nWaitTicketNum - nProcessCnt;
|
||
|
||
UpdateProcessIndexAsync(0, nProcessCnt);
|
||
}
|
||
|
||
void CDNWaitUserManager::UpdateProcessIndexAsync(int nIndex, int nCount)
|
||
{
|
||
//상위에서 동기잡고 와야합니다.
|
||
std::vector <std::pair<int, int>>::iterator ii;
|
||
for (ii = m_OutList.begin(); ii != m_OutList.end(); ii++)
|
||
{
|
||
if ((*ii).first == nIndex)
|
||
break;
|
||
}
|
||
|
||
if (ii != m_OutList.end())
|
||
(*ii).second += nCount;
|
||
else
|
||
m_OutList.push_back(std::make_pair(nIndex, nCount));
|
||
}
|