Files
Client/Server/ManageTool/ManageLibrary/UserManage/UserStatistics.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

493 lines
13 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "stdafx.h"
#include "UserStatistics.h"
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Log/ServerLog.h>
#include <Utility/Setup/ServerSetup.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Network/Dispatch/ManageServer/StatServerMultiDispatch.h>
#include <atlTime.h>
const TCHAR* g_szAppName = _T("HANGAME_SEND_USER_INFO");
CUserStatistics& CUserStatistics::GetInstance()
{
static CUserStatistics userStatistics;
return userStatistics;
}
CUserStatistics::CUserStatistics()
{
SetSetupFileName(_T("./RylSetupServerGroup.ini"));
Load();
}
CUserStatistics::~CUserStatistics()
{
}
void CUserStatistics::SetSetupFileName(const TCHAR* szFileName)
{
if(0 != szFileName)
{
_sntprintf(m_szSetupFileName, MAX_PATH - 1, "%s", szFileName);
m_szSetupFileName[MAX_PATH - 1] = 0;
}
}
bool CUserStatistics::Load()
{
StatisticsLock::Syncronize sync(m_Lock);
TCHAR szKeyName[MAX_PATH];
TCHAR szValue[MAX_PATH];
m_ServerGroupNames.clear();
unsigned long dwMaxServerGroup = GetPrivateProfileInt(g_szAppName, "MAX_GROUP_NAME", 0, m_szSetupFileName);
for(unsigned long dwCount = 0; dwCount < dwMaxServerGroup; ++dwCount)
{
_sntprintf(szKeyName, MAX_PATH - 1, "GROUP_KEY%u", dwCount);
szKeyName[MAX_PATH - 1] = 0;
unsigned long dwKey = GetPrivateProfileInt(g_szAppName, szKeyName, 0xFFFFFFFF, m_szSetupFileName);
if(dwKey != 0xFFFFFFFF)
{
_sntprintf(szKeyName, MAX_PATH - 1, "GROUP_NAME%u", dwCount);
szKeyName[MAX_PATH - 1] = 0;
GetPrivateProfileString(g_szAppName, szKeyName, 0, szValue, MAX_PATH, m_szSetupFileName);
m_ServerGroupNames.insert(ServerGroupNames::value_type(dwKey, szValue));
}
}
GetPrivateProfileString(g_szAppName, "HANGAME_SERVER_DOMAIN", 0, szValue, MAX_PATH, m_szSetupFileName);
unsigned short usPort = static_cast<unsigned short>(
GetPrivateProfileInt(g_szAppName, "HANGAME_SERVER_PORT", 0, m_szSetupFileName));
hostent* lphost = gethostbyname(szValue);
if (0 != lphost)
{
for (int nCount = 0; 0 != lphost->h_addr_list[nCount]; ++nCount )
{
m_HangameAddress.push_back(
INET_Addr(*(in_addr*)lphost->h_addr_list[nCount], usPort));
}
}
return true;
}
void CUserStatistics::InternalSetUserNum(unsigned long dwRunID, unsigned long dwServerID, int nCurrentUserNum)
{
// ServerID <20><>Ģ üũ dwServerID
SERVER_ID serverID;
serverID.dwID = dwServerID;
if(0 <= serverID.GetChannel() && 0 <= serverID.GetGroup() && 0 <= serverID.GetZone())
{
UserNumTable::iterator pos = m_CurrentUsers.find(dwServerID);
if(pos != m_CurrentUsers.end())
{
// <20><> <20><><EFBFBD><EFBFBD>
pos->second = nCurrentUserNum;
}
else
{
// <20><> <20><><EFBFBD><EFBFBD>
pos = m_CurrentUsers.insert(pos, UserNumTable::value_type(dwServerID, nCurrentUserNum));
m_RunIDTable.insert(RunIDTable::value_type(dwRunID, pos));
}
}
}
int CUserStatistics::GetUserNum(unsigned long dwServerID)
{
StatisticsLock::Syncronize sync(m_Lock);
UserNumTable::iterator find = m_CurrentUsers.find(dwServerID);
return (find != m_CurrentUsers.end()) ? find->second : 0;
}
int CUserStatistics::GetTotalUserNum()
{
StatisticsLock::Syncronize sync(m_Lock);
UserNumTable::iterator pos = m_CurrentUsers.begin();
UserNumTable::iterator end = m_CurrentUsers.end();
int nTotalUser = 0;
for(; pos != end; ++pos)
{
int nCurrentUser = pos->second;
if(0 < nCurrentUser)
{
nTotalUser += pos->second;
}
}
return nTotalUser;
}
int CUserStatistics::GetGroupUserNum(char cGroupNum)
{
StatisticsLock::Syncronize sync(m_Lock);
UserNumTable::iterator pos = m_CurrentUsers.begin();
UserNumTable::iterator end = m_CurrentUsers.end();
int nTotalUser = 0;
SERVER_ID serverID;
for(; pos != end; ++pos)
{
serverID.dwID = pos->first;
if(cGroupNum == serverID.GetGroup())
{
int nCurrentUser = pos->second;
if(0 < nCurrentUser)
{
nTotalUser += pos->second;
}
}
}
return nTotalUser;
}
void CUserStatistics::InternalClearRunID_UserNum(unsigned long dwRunID)
{
std::pair<RunIDTable::iterator, RunIDTable::iterator>
resultPair = m_RunIDTable.equal_range(dwRunID);
RunIDTable::iterator pos = resultPair.first;
for(; pos != resultPair.second; ++pos)
{
if(0 != pos->second->second)
{
pos->second->second = 0;
}
}
}
void CUserStatistics::InternalClearGroupUserNum(unsigned char cGroupNum)
{
UserNumTable::iterator pos = m_CurrentUsers.begin();
UserNumTable::iterator end = m_CurrentUsers.end();
SERVER_ID serverID;
for(; pos != end; ++pos)
{
serverID.dwID = pos->first;
if(cGroupNum == serverID.GetGroup())
{
pos->second = 0;
}
}
}
void CUserStatistics::SerializeIn(unsigned long dwRunID,
ServerManage::UserNumPair* lpUserNumPair, unsigned long dwPairNum)
{
if(0 != lpUserNumPair)
{
StatisticsLock::Syncronize sync(m_Lock);
ServerManage::UserNumPair* lpUserNumPairEnd = lpUserNumPair + dwPairNum;
for(; lpUserNumPair != lpUserNumPairEnd; ++lpUserNumPair)
{
InternalSetUserNum(dwRunID, lpUserNumPair->m_dwServerID,
lpUserNumPair->m_nUserNum);
}
}
}
void CUserStatistics::SendStatisticsToHanGame()
{
if(0 == GetPrivateProfileInt(g_szAppName, "SEND_HANGAME_INFO", 0, m_szSetupFileName))
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
return;
}
char szGameID[256];
GetPrivateProfileString(g_szAppName, "SEND_GAME_ID", _T("RYL"), szGameID, 256, m_szSetupFileName);
UserNumTable CurrentUsers;
{
StatisticsLock::Syncronize sync(m_Lock);
CurrentUsers = m_CurrentUsers;
}
const int MAX_BUFFER = 3192;
char szBuffer[MAX_BUFFER];
SERVER_ID ServerID;
int nUserNum = 0;
int nLength = 0;
size_t nMaxGroupName = m_ServerGroupNames.size();
SOCKADDR_IN ServerAddr;
memset(&ServerAddr, 0, sizeof(SOCKADDR_IN));
UserNumTable::iterator pos = CurrentUsers.begin();
UserNumTable::iterator end = CurrentUsers.end();
for(; pos != end; ++pos)
{
ServerID.dwID = pos->first;
nUserNum = pos->second;
if(ServerID.GetZone() - 1 < 0 || ServerID.GetChannel() < 0)
{
}
else if(0 < nUserNum)
{
ServerGroupNames::iterator pos = m_ServerGroupNames.find(ServerID.GetGroup());
if(pos != m_ServerGroupNames.end())
{
// TODO : Sparrowhawk.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ȳ<EFBFBD><C8B2>.. ù <20><><EFBFBD><EFBFBD> GrandCost<73><74> <20><> <20><>ȣ<EFBFBD><C8A3> 1<>̴<EFBFBD>.
// <20>׷<EFBFBD><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><>ȣ<EFBFBD><C8A3> 0<><30><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
// GetServerSession<6F><6E><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>.
nLength = _snprintf(szBuffer, MAX_BUFFER,
"GET /gamestatic/gameconn.nhn?m=gameconn&gameid=%s&servername=%s-%d-%d&conncount=%d\n\n",
szGameID,
pos->second.c_str(),
ServerID.GetZone() - 1,
ServerID.GetChannel(),
nUserNum);
// <20><><EFBFBD><EFBFBD>
AddressList::iterator pos = m_HangameAddress.begin();
AddressList::iterator end = m_HangameAddress.end();
bool bSucceeded = false;
for (; pos != end && !bSucceeded; ++pos)
{
INET_Addr& address = *pos;
SOCKET hSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == hSocket)
{
ERRLOG1(g_Log, "Hangame user send failed : socket create failed - %d", WSAGetLastError());
}
else if (SOCKET_ERROR == connect(hSocket, &address.get_addr(), address.get_size()))
{
ERRLOG1(g_Log, "Hangame user send failed : connect failed - %d", WSAGetLastError());
}
else if (SOCKET_ERROR == send(hSocket, szBuffer, nLength, 0))
{
ERRLOG1(g_Log, "Hangame user send failed : send failed - %d", WSAGetLastError());
}
else
{
INFLOG2(g_Log, "'%s':%d bytes send complete", szBuffer, nLength);
bSucceeded = true;
}
shutdown(hSocket, SD_SEND);
closesocket(hSocket);
}
}
}
}
}
void CUserStatistics::SendStatisticsToStatServer()
{
int nSendGlobal =
GetPrivateProfileInt("STATSERVER_INFO", "SEND_STAT_SERVER_1ST", 0, m_szSetupFileName);
int nSendLocal =
GetPrivateProfileInt("STATSERVER_INFO", "SEND_STAT_SERVER_2ND", 0, m_szSetupFileName);
int nNation =
GetPrivateProfileInt("GENERAL", "NATION_INDEX", 0, m_szSetupFileName);
if((0 == nSendGlobal) && (0 == nSendLocal))
{
return;
}
if(UCHAR_MAX < nNation)
{
ERRLOG1(g_Log, "Nation index is invalid: NationIndex-%d", nNation);
return;
}
SERVER_ID ServerID;
int nUserNum = 0;
UserNumTable CurrentUsers;
{
StatisticsLock::Syncronize sync(m_Lock);
CurrentUsers = m_CurrentUsers;
}
const int MAX_USER_STAT = 1000;
const int BUFFER_SIZE = sizeof(ServerManage::PktUserStat) +
sizeof(ServerManage::UserStatData) * MAX_USER_STAT;
char szBuffer[BUFFER_SIZE];
ServerManage::PktUserStat* lpPktUserStat =
reinterpret_cast<ServerManage::PktUserStat*>(szBuffer);
ServerManage::UserStatData* lpUserStatData =
reinterpret_cast<ServerManage::UserStatData*>(lpPktUserStat + 1);
unsigned short nUserStatData = 0;
SYSTEMTIME stCurrentTime;
GetLocalTime(&stCurrentTime);
_snprintf(lpPktUserStat->m_szSendingTime, ServerManage::PktUserStat::MAX_DATE,
"%04d-%02d-%02d %02d:%02d:%02d",
stCurrentTime.wYear, stCurrentTime.wMonth, stCurrentTime.wDay,
stCurrentTime.wHour, stCurrentTime.wMinute, stCurrentTime.wSecond);
UserNumTable::iterator pos = CurrentUsers.begin();
UserNumTable::iterator end = CurrentUsers.end();
const int MAX_BUFFER = 256;
char szGlobalStatServerIP[MAX_BUFFER], szLocalStatServerIP[MAX_BUFFER];
GetPrivateProfileString("STATSERVER_INFO", "STAT_SERVER_1ST_IP", 0,
szGlobalStatServerIP, MAX_BUFFER, m_szSetupFileName);
GetPrivateProfileString("STATSERVER_INFO", "STAT_SERVER_2ND_IP", 0,
szLocalStatServerIP, MAX_BUFFER, m_szSetupFileName);
GET_MULTI_DISPATCH(lpGlobalStatDispatch, inet_addr(szGlobalStatServerIP),
CStatServerMultiDispatch, CStatServerMultiDispatch::GetDispatchTable());
GET_MULTI_DISPATCH(lpLocalStatDispatch, inet_addr(szLocalStatServerIP),
CStatServerMultiDispatch, CStatServerMultiDispatch::GetDispatchTable());
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
for(; pos != end; ++pos)
{
ServerID.dwID = pos->first;
nUserNum = pos->second;
if(nUserNum < 0)
{
nUserNum = 0;
}
if(ServerID.GetZone() - 1 < 0 || ServerID.GetChannel() < 0)
{
ERRLOG1(g_Log, "Invalid serverID: %u", ServerID.dwID);
}
else if(CServerSetup::GameServer == ServerID.GetType())
{
lpUserStatData->m_dwServerID = ServerID.dwID;
lpUserStatData->m_nNation = nNation;
lpUserStatData->m_nUserNum = nUserNum;
INFLOG3(g_Log, "[UserStat Sended] NationCode: %d/ServerID: 0x%08x/UserNum: %d",
nNation, ServerID.dwID, nUserNum);
++lpUserStatData;
++nUserStatData;
}
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if(nUserStatData == MAX_USER_STAT - 1)
{
lpPktUserStat->m_usUserStatDataNum = nUserStatData;
if((NULL != lpGlobalStatDispatch) && (1 == nSendGlobal))
{
lpGlobalStatDispatch->GetSendStream().WrapCompress(szBuffer,
sizeof(ServerManage::PktUserStat) + sizeof(ServerManage::UserStatData) * nUserStatData,
ServerManage::CMD::UPDATE_USER_STATUS, 0, 0);
}
if((NULL != lpLocalStatDispatch) && (1 == nSendLocal))
{
lpLocalStatDispatch->GetSendStream().WrapCompress(szBuffer,
sizeof(ServerManage::PktUserStat) + sizeof(ServerManage::UserStatData) * nUserStatData,
ServerManage::CMD::UPDATE_USER_STATUS, 0, 0);
}
lpUserStatData = reinterpret_cast<ServerManage::UserStatData*>(lpPktUserStat + 1);
nUserStatData = 0;
}
if(0 < nUserStatData)
{
lpPktUserStat->m_usUserStatDataNum = nUserStatData;
if((NULL != lpGlobalStatDispatch) && (1 == nSendGlobal))
{
lpGlobalStatDispatch->GetSendStream().WrapCompress(szBuffer,
sizeof(ServerManage::PktUserStat) + sizeof(ServerManage::UserStatData) * nUserStatData,
ServerManage::CMD::UPDATE_USER_STATUS, 0, 0);
}
if((NULL != lpLocalStatDispatch) && (1 == nSendLocal))
{
lpLocalStatDispatch->GetSendStream().WrapCompress(szBuffer,
sizeof(ServerManage::PktUserStat) + sizeof(ServerManage::UserStatData) * nUserStatData,
ServerManage::CMD::UPDATE_USER_STATUS, 0, 0);
}
}
}
void CUserStatistics::CheckClearUser(PktBase* lpPktBase)
{
StatisticsLock::Syncronize sync(m_Lock);
if(sizeof(ServerManage::ManageCommand) <= lpPktBase->GetLen())
{
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
int nProcessStatusNum = int(lpManageCommand->usDataLen / sizeof(ServerManage::ProcessStatus));
if(sizeof(ServerManage::ManageCommand) + lpManageCommand->usDataLen == lpPktBase->GetLen()
&& lpManageCommand->usDataLen == nProcessStatusNum * sizeof(ServerManage::ProcessStatus))
{
ServerManage::ProcessStatus* lpProcessStatus =
reinterpret_cast<ServerManage::ProcessStatus*>(lpManageCommand + 1);
ServerManage::ProcessStatus* lpProcessStatusEnd = lpProcessStatus + nProcessStatusNum;
for(; lpProcessStatus != lpProcessStatusEnd; ++lpProcessStatus)
{
if(0 == (ServerManage::PROCESS_RUNNING & lpProcessStatus->m_dwStatusFlags))
{
InternalClearRunID_UserNum(lpProcessStatus->m_dwRunID);
}
}
}
}
}