Files
Client/Server/RylServerProject/RylDBAgentServer/Ranking/RankingDBMgr.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

284 lines
8.4 KiB
C++

#include "stdafx.h"
#include "RankingDBMgr.h"
#include <DB/DBComponent.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/RankingPacket.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Utility/Setup/ServerSetup.h>
#include <Utility/Compress/MiniLZO/miniLZOWrapper.h>
#include <Log/ServerLog.h>
static CRankingDBMgr* rankingMgr = NULL;
CRankingDBMgr& CRankingDBMgr::GetInstance()
{
// static CRankingDBMgr rankingMgr;
if(!rankingMgr)
rankingMgr = new CRankingDBMgr();
return *rankingMgr;
}
VOID CRankingDBMgr::ReleaseInstance()
{
if(rankingMgr)
{
delete rankingMgr;
rankingMgr = NULL;
}
}
CRankingDBMgr::CRankingDBMgr()
{
memset(m_aryRanking, 0, sizeof(RankingNode) * CClass::MAX_CLASS * MAX_DECLARE_RANK_NUM);
SERLOG0(g_Log, "CRankingDBMgr::CRankingDBMgr()");
}
CRankingDBMgr::~CRankingDBMgr()
{
}
bool CRankingDBMgr::Initialize()
{
const unsigned char MAX_RANKING_CLASS_NUM = 14;
const int nClassList[MAX_RANKING_CLASS_NUM] =
{
// 인간 1st클래스
CClass::Defender,
CClass::Warrior,
CClass::Assassin,
CClass::Archer,
CClass::Sorcerer,
CClass::Enchanter,
CClass::Priest,
CClass::Cleric,
// 아칸 1st클래스
CClass::Templar,
CClass::Attacker,
CClass::Gunner,
CClass::RuneOff,
CClass::LifeOff,
CClass::ShadowOff
};
char szQuery[CDBComponent::QUERY_BUFFER_LEN] = "";
int nListNum = 0;
memset(m_aryRanking, 0, sizeof(RankingNode) * CClass::MAX_CLASS * MAX_DECLARE_RANK_NUM);
// 클래스 별로 MAX_DECLARE_RANK_NUM(= 100)만큼 명성 별로 리스트에 채워 넣는다.
for (unsigned char cCount = 0; cCount < MAX_RANKING_CLASS_NUM; ++cCount)
{
int nClass = nClassList[cCount];
_snprintf(szQuery, CDBComponent::QUERY_BUFFER_LEN - 1,
"SELECT top %d CharInfo.Name, CharInfo.Fame, CharInfo.LEVEL, CharInfo.Class "
"FROM CharInfo, TblUnifiedCharList "
"WHERE TblUnifiedCharList.OldServerGroupID = %d AND "
"TblUnifiedCharList.NewCID = CharInfo.CID AND "
"CharInfo.Class = %d AND CharInfo.Fame != 0 ORDER BY CharInfo.Fame DESC, CharInfo.LEVEL DESC",
MAX_DECLARE_RANK_NUM, CServerSetup::GetInstance().GetAgentServerType(), nClass);
szQuery[CDBComponent::QUERY_BUFFER_LEN - 1] = 0;
if (!CDBSingleObject::GetInstance().Select(szQuery,
(void **)m_aryRanking[nClass], sizeof(RankingNode), 0, MAX_DECLARE_RANK_NUM, &nListNum))
{
ERRLOG3(g_Log, "Class:%d / Ranking 얻기 쿼리를 실패했습니다 : %s : %s",
nClass, CDBSingleObject::GetInstance().GetErrorString(), szQuery);
return false;
}
}
return true;
}
void CRankingDBMgr::DeleteRanking(RankingNode& node)
{
if (CClass::JOB_CHANGE_1ST == CClass::GetJobLevel(node.m_cClass))
{
bool bUpdate = false;
for (int nRankIndex = 0; nRankIndex < MAX_DECLARE_RANK_NUM; nRankIndex++)
{
if (0 == strcmp("", m_aryRanking[node.m_cClass][nRankIndex].m_szCharName))
{
break;
}
if (0 == strcmp(node.m_szCharName, m_aryRanking[node.m_cClass][nRankIndex].m_szCharName))
{
memset(&m_aryRanking[node.m_cClass][nRankIndex], 0, sizeof(RankingNode));
break;
}
}
}
}
void CRankingDBMgr::UpdateRanking(RankingNode& node)
{
if (CClass::JOB_CHANGE_1ST == CClass::GetJobLevel(node.m_cClass))
{
bool bUpdate = false;
for (int nRankIndex = 0; nRankIndex < MAX_DECLARE_RANK_NUM; nRankIndex++)
{
if (0 == strcmp("", m_aryRanking[node.m_cClass][nRankIndex].m_szCharName))
{
break;
}
if (0 == strcmp(node.m_szCharName, m_aryRanking[node.m_cClass][nRankIndex].m_szCharName))
{
if (node.m_dwPoint == m_aryRanking[node.m_cClass][nRankIndex].m_dwPoint &&
node.m_cLevel == m_aryRanking[node.m_cClass][nRankIndex].m_cLevel &&
node.m_cClass == m_aryRanking[node.m_cClass][nRankIndex].m_cClass)
{
return;
}
// 이미 랭커인 경우 최신 정보로 업데이트
m_aryRanking[node.m_cClass][nRankIndex] = node;
bUpdate = true;
break;
}
}
if (!bUpdate)
{
if (m_aryRanking[node.m_cClass][MAX_DECLARE_RANK_NUM-1] < node)
{
// 랭킹 리스트에 진입 (최하위보다 수치가 높음)
m_aryRanking[node.m_cClass][MAX_DECLARE_RANK_NUM-1] = node;
bUpdate = true;
}
}
if (bUpdate)
{
std::sort(&m_aryRanking[node.m_cClass][0],
&m_aryRanking[node.m_cClass][MAX_DECLARE_RANK_NUM],
RankingNode::ComparePoint());
SendRankingInfo(node);
}
}
}
void CRankingDBMgr::SendRankingInfo(const RankingNode& node)
{
const unsigned short MAX_RANKING_PACKET_SIZE = sizeof(PktRankingInfo) + sizeof(RankingNode);
char szBuffer[MAX_RANKING_PACKET_SIZE];
memset(szBuffer, 0, sizeof(char) * MAX_RANKING_PACKET_SIZE);
PktRankingInfo* lpPktRankingInfo =
reinterpret_cast<PktRankingInfo*>(szBuffer);
RankingNode* lpRankingNode =
reinterpret_cast<RankingNode*>(lpPktRankingInfo + 1);
lpPktRankingInfo->m_wNum = 1;
*lpRankingNode = node;
if(PacketWrap::WrapHeader(szBuffer, MAX_RANKING_PACKET_SIZE, CmdRankingInfo, 0, 0))
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
szBuffer, MAX_RANKING_PACKET_SIZE, CmdRankingInfo));
}
}
void CRankingDBMgr::SendRankingInfo(CSendStream& SendStream)
{
SERLOG0(g_Log, "CRankingDBMgr::SendRankingInfo : Start");
const unsigned short MAX_RANKING_PACKET_SIZE =
sizeof(PktRankingInfo) + sizeof(RankingNode) * NODE_NUM_PER_SENDING;
const unsigned short MAX_COMPRESSED_RANKING_PACKET_SIZE =
static_cast<unsigned short>(CMiniLZO::GetLeastCompressBuffer(MAX_RANKING_PACKET_SIZE));
char* szDataBuffer = new char[MAX_RANKING_PACKET_SIZE];
char* szCompressedBuffer = new char[MAX_COMPRESSED_RANKING_PACKET_SIZE];
if(0 != szDataBuffer && 0 != szCompressedBuffer)
{
PktRankingInfo* lpRankingInfo = reinterpret_cast<PktRankingInfo*>(szDataBuffer);
RankingNode* lpRankingNode = reinterpret_cast<RankingNode*>(lpRankingInfo + 1);
unsigned short wNum = 0;
for (int nClassIndex = 0; nClassIndex < CClass::MAX_CLASS; ++nClassIndex)
{
for (int nRankIndex = 0; nRankIndex < MAX_DECLARE_RANK_NUM; ++nRankIndex)
{
if (0 == strcmp("", m_aryRanking[nClassIndex][nRankIndex].m_szCharName))
break;
*lpRankingNode = m_aryRanking[nClassIndex][nRankIndex];
++lpRankingNode;
++wNum;
if (NODE_NUM_PER_SENDING <= wNum)
{
// NODE_NUM_PER_SENDING의 단위로 끊어서 전송한다. (패킷 크기 제한 때문)
lpRankingInfo->InitPtHead(
static_cast<unsigned short>(sizeof(PktRankingInfo) + sizeof(RankingNode) * wNum),
CmdRankingInfo, 0, 0);
lpRankingInfo->m_wNum = wNum;
unsigned long dwCompressedSize = MAX_COMPRESSED_RANKING_PACKET_SIZE;
if(PacketWrap::WrapCompress(szCompressedBuffer, dwCompressedSize, szDataBuffer,
static_cast<unsigned short>(sizeof(PktRankingInfo) + sizeof(RankingNode) * wNum),
CmdRankingInfo, 0, 0))
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
szCompressedBuffer, dwCompressedSize, CmdRankingInfo));
}
SERLOG2(g_Log, "CRankingDBMgr::SendRankingInfo : %d, Class : %d", wNum, nClassIndex);
lpRankingInfo = reinterpret_cast<PktRankingInfo*>(szDataBuffer);
lpRankingNode = reinterpret_cast<RankingNode*>(lpRankingInfo + 1);
wNum = 0;
}
}
}
// 남은 리스트를 마저 보낸다.
lpRankingInfo->m_wNum = wNum;
unsigned long dwCompressedSize = MAX_COMPRESSED_RANKING_PACKET_SIZE;
if(PacketWrap::WrapCompress(szCompressedBuffer, dwCompressedSize, szDataBuffer,
static_cast<unsigned short>(sizeof(PktRankingInfo) + sizeof(RankingNode) * wNum),
CmdRankingInfo, 0, 0))
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
szCompressedBuffer, dwCompressedSize, CmdRankingInfo));
}
SERLOG1(g_Log, "CRankingDBMgr::SendRankingInfo : %d End", wNum);
}
if(0 == szDataBuffer)
{
delete [] szDataBuffer;
szDataBuffer = 0;
}
if(0 == szCompressedBuffer)
{
delete [] szCompressedBuffer;
szCompressedBuffer = 0;
}
}