Files
Client/Server/RylServerProject/RylGameLibrary/Network/Dispatch/GameClient/GameClientDispatch.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

570 lines
21 KiB
C++

#include "stdafx.h"
#include <boost/pool/pool_alloc.hpp>
#include <Network/Session/Session.h>
#include <Network/XORCrypt/XORCrypt.h>
#include <Network/Packet/PacketBase.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Packet/PacketStruct/CharAttackPacket.h>
#include <Stream/Buffer/Buffer.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Creature/Character/Character.h>
#include <GameGuardLib/ggerror.h>
#include <mmsystem.h>
#include "PacketParse.h"
#include "GameClientDispatch.h"
// 함수 선언
bool LogFailDispatch(CGameClientDispatch& GameClientDispatch,
const char* szDetailText, const unsigned char cCmd);
CGameClientDispatchTable& CGameClientDispatchTable::GetInstance()
{
static CGameClientDispatchTable gameClientDispatchTable;
return gameClientDispatchTable;
}
CGameClientDispatchTable::CGameClientDispatchTable()
: CPacketDispatchTable<CGameClientDispatch::FnProcess>(UCHAR_MAX)
{
using namespace GameClientParsePacket;
// 기본적인 Process들이 들어갈 것. ( character관련... )
// 캐릭터 아이템 관련 - ParseCharItem.cpp
AddDispatch(CmdCharTakeItem, ParseCharTakeItem); // 아이템 이동 및 스택
AddDispatch(CmdCharSwapItem, ParseCharSwapItem); // 아이템 스왑
AddDispatch(CmdCharRepairItem, ParseCharRepairItem); // 아이템 수리
AddDispatch(CmdCharRepairAllItem, ParseCharRepairAllItem); // 아이템 수리 (장비하고 있는 아이템 모두)
AddDispatch(CmdCharUseItem, ParseCharUseItem); // 아이템 사용
AddDispatch(CmdCharTradeItem, ParseCharTradeItem); // 아이템 거래
AddDispatch(CmdCharEquipShopInfo, ParseCharEquipShopInfo); // NPC 장비 상점 정보
AddDispatch(CmdCharPickUp, ParseCharPickUp); // 아이템 집기
AddDispatch(CmdCharPullDown, ParseCharPullDown); // 아이템 떨구기
AddDispatch(CmdCharSplitItem, ParseCharSplitItem); // 아이템 나누기
AddDispatch(CmdCharTakeGold, ParseCharTakeGold); // 돈 다루기
AddDispatch(CmdDeposit, ParseCharDepositCmd); // 창고 관련 패킷들
AddDispatch(CmdCharAutoRouting, ParseCharAutoRouting); // 오토 루팅
AddDispatch(CmdCharUseCashItem, ParseCharUseCashItem); // 캐쉬아이템
// 캐릭터 아이템 업그레이드 관련 - ParseCharUpgradeItem.cpp
AddDispatch(CmdCharInstallSocket, ParseCharInstallSocket); // 아이템 인스톨 소켓
AddDispatch(CmdCharItemChemical, ParseCharItemChemical); // 아이템 합성
AddDispatch(CmdCharUpgradeItem, ParseCharUpgradeItem); // 아이템 업그레이드
AddDispatch(CmdCharItemOptionGraft, ParseCharItemOptionGraft); // 아이템 옵션 이식
AddDispatch(CmdCharItemCompensation, ParseCharItemCompensation); // 아이템 보상 판매
// 캐릭터 스킬 관련 - ParseCharSkill.cpp
AddDispatch(CmdCharUseSkill, ParseCharUseSkill); // 스킬 사용
// AddDispatch(CmdCharSkillLock, ParseCharSkillLock); // 스킬 락
// AddDispatch(CmdCharSkillUnLock, ParseCharSkillUnLock); // 스킬 락 해제
AddDispatch(CmdCharSkillErase, ParseCharSkillErase); // 스킬 지우기
// 캐릭터 전투 관련 패킷 - ParseCharAttack.cpp
AddDispatch(CmdCharAttack, ParseCharAttack); // 공격 패킷
AddDispatch(CmdCharSwitchEQ, ParseCharSwitchEQ); // 장비 바꾸기
AddDispatch(CmdCharRespawn, ParseCharRespawn); // 캐릭터 리스폰
AddDispatch(CmdCharRespawnWaitQueue, ParseCharRespawnWaitQueue); // 리스폰 큐 대기인 정보 (배틀그라운드용)
AddDispatch(CmdCharRespawnInfo, ParseCharRespawnInfo); // 리스폰 정보 (리스폰 위치들)
AddDispatch(CmdCharRespawnAreaInfo, ParseCharRespawnAreaInfo); // 리스폰 지역 세부 정보
// AddDispatch(CmdCharMoveUpdate, ParseCharMoveUpdate); // 캐릭터 움직임 업데이트
AddDispatch(CmdCharDuelCmd, ParseCharDuelCmd); // 듀얼 패킷 명령
AddDispatch(CmdCharPeaceMode, ParseCharPeaceMode); // 반전 모드
AddDispatch(CmdCharSummonCmd, ParseCharSummonCmd); // 소환수 명령
// 원래는 UDP p2p패킷이지만 서버로 올림
AddDispatch(CmdCharMove, ParseCharMoveEx);
// 캐릭터 레벨업 관련 패킷 - ParseCharLevelUp.cpp
AddDispatch(CmdCharClassUpgrade, ParseCharClassUpgrade); // 클래스 업그레이드
AddDispatch(CmdCharIncreasePoint, ParseCharIncreasePoint); // IP 증가 패킷
AddDispatch(CmdCharStateRedistribution, ParseCharStateRedistribution); // IP 증가 패킷
AddDispatch(CmdCharStatusRetrain, ParseCharStatusRetrain); // 캐릭터 스테이터스 재훈련
// 캐릭터 커뮤니티 관련 패킷 - ParseCharCommunity.cpp
AddDispatch(CmdCharExchangeCmd, ParseCharExchangeCmd); // 교환 패킷 명령
AddDispatch(CmdCharPartyCmd, ParseCharPartyCmd); // 파티 패킷 명령
AddDispatch(CmdCharPartyFind, ParseCharPartyFind); // 파티 찾기
AddDispatch(CmdCharStallOpen, ParseCharStallOpen); // 캐틱터 노점상 개설
AddDispatch(CmdCharStallRegisterItem, ParseCharStallRegisterItem); // 캐틱터 노점상 아이템 등록
AddDispatch(CmdCharStallEnter, ParseCharStallEnter); // 캐틱터 노점상 입장
AddDispatch(CmdFriendAddRequest, ParseCharFriendAdd); // 친구 추가
AddDispatch(CmdFriendRemoveRequest, ParseCharFriendRemove); // 친구 삭제
AddDispatch(CmdFriendEtcRequest, ParseCharFriendEtc); // 기타
AddDispatch(CmdCreateGuild, ParseCharCreateGuild); // 길드 생성
AddDispatch(CmdGuildCmd, ParseCharGuildCmd); // 길드 멤버 관련 명령
AddDispatch(CmdGuildMark, ParseCharGuildMark); // 길드 마크 변경
AddDispatch(CmdGuildLevel, ParseCharGuildLevel); // 길드 레벨 변경
AddDispatch(CmdGuildRelation, ParseCharGuildRelation); // 길드 관계 변경
AddDispatch(CmdGuildInclination, ParseCharGuildInclination); // 길드 성향 변경
AddDispatch(CmdGuildList, ParseCharGuildList); // 길드 리스트
AddDispatch(CmdGuildRight, ParseCharGuildRight); // 길드 권한 설정
AddDispatch(CmdGuildMemberList, ParseCharGuildMemberList); // 길드 멤버 리스트
AddDispatch(CmdGuildSafe, ParseCharGuildSafe); // 길드 금고
AddDispatch(CmdGuildHostilityList, ParseCharGuildHostilityList); // 적대 길드 현황 리스트
AddDispatch(CmdGuildRelationInfo, ParseCharGuildRelationInfo); // 길드의 관계 리스트 요청
// 어드민 관련 패킷 - ParseCharAdmin.cpp
AddDispatch(CmdCharAdminCmd, ParseCharAdminCmd); // 어드민 커맨드
AddDispatch(CmdCharNameChange, ParseCharNameChange); // 캐릭터 이름 변경
// 캐릭터 퀘스트 관련 패킷 - ParseCharQuest.cpp
AddDispatch(CmdCharStartQuest, ParseCharStartQuest); // 퀘스트 시작
AddDispatch(CmdCharOperateTrigger, ParseCharOperateTrigger); // 트리거 발동
AddDispatch(CmdCharCancelQuest, ParseCharCancelQuest); // 퀘스트 취소
// 캐릭터 기타 패킷 - ParseCharEtc.cpp
AddDispatch(CmdCharSuicide, ParseCharSuicide); // 캐릭터 자살
AddDispatch(CmdCharBindPosition, ParseCharBindPosition); // 캐릭터 바인드 포지션
AddDispatch(CmdCharQuickSlotMove, ParseCharQuickSlotMove); // 캐릭터 퀵 슬롯 이동
AddDispatch(CmdCharControlOption, ParseCharControlOption); // 캐릭터 옵션 조정
AddDispatch(CmdCharAuthorizePanel, ParseCharAuthorizePanel);
AddDispatch(CmdCharFameInfo, ParseCharFameInfo); // 캐릭터 명성(공헌도) 정보 요청
AddDispatch(CmdRankingInfo, ParseCharRankingInfo); // 랭킹 정보
// 배틀 그라운드 서버군 패킷 - ParseCharBGServer.cpp
AddDispatch(CmdBGServerMapList, ParseCharBGServerMapList); // 배틀 그라운드 서버군 맵(방) 정보 리스트
AddDispatch(CmdBGServerResultList, ParseCharBGServerResultList); // 배틀 그라운드 서버군 맵(방) 결과 리스트
AddDispatch(CmdBGServerMoveZone, ParseCharBGServerMoveZone); // 배틀 그라운드 서버군 존 이동 (맵(방) 이동)
AddDispatch(CmdBGServerMileageChange, ParseCharBGServerMileageChange); // 배틀 그라운드 서버군 환전소 명령
AddDispatch(CmdBGServerCharSlot, ParseCharBGServerCharSlot); // 배틀 그라운드 서버 정섭 캐릭터 정보 요청
// 공성 패킷 - ParseCharCastle.cpp
AddDispatch(CmdCastleCmd, ParseCharCastleCmd); // 성 관련 오브젝트 명령
AddDispatch(CmdCampCmd, ParseCharCampCmd); // 길드 요새 명령
AddDispatch(CmdSiegeArmsCmd, ParseCharSiegeArmsCmd); // 공성 병기 명령
AddDispatch(CmdCastleRight, ParseCharCastleRight); // 성 권한 설정
AddDispatch(CmdCampRight, ParseCharCampRight); // 길드 요새 권한 설정
// 채팅 패킷 - ParseCharChat.cpp
AddDispatch(CmdCharWhisper, ParseCharWhisper); // 속삭임
AddDispatch(CmdCharChat, ParseCharChat); // 캐틱터 채팅
AddDispatch(CmdCharCastObjectInfo, ParseCastObjectInfo); // 오브젝트 던지기 패킷 정보
AddDispatch(CmdCharInstallRuneSocket, ParseCharInstallRuneSocket); // 룬설치, 삭제 관련 정보.
AddDispatch(CmdTakeMaterial, ParseCharTakeMaterial); // 길드 요새 자재 넣기/빼기
AddDispatch(CmdTakeCastleJewel, ParseCharTakeCastleJewel); // 성 상징물 보석 아이템 넣기/빼기
AddDispatch(CmdWarOnOff, ParseWarOnOff); // 길드전, 국가전 플래그 바꾸기
AddDispatch(CmdKeyInfo, ParseKeyInfo); // 조이스틱 키 정보 관련.
}
CGameClientDispatch::CGameClientDispatch(CSession& Session,
CGameClientDispatchTable& GameClientDispatchTable)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE),
m_lpCharacter(0),
m_dwUID(0),
m_GameClientDispatchTable(GameClientDispatchTable),
m_dwMoveServerID(0)
{
// edith 2009.08.11 게임가드 2.5 업그레이드
// m_CSAuth.Init();
m_CSAuth2.Init();
DETLOG2(g_Log, "DP:0x%p/UID:%u/GameClientDispatch Created", this, m_dwUID);
}
CGameClientDispatch::~CGameClientDispatch()
{
CGameClientDispatch::Disconnected();
// 객체 소멸 로그
DETLOG2(g_Log, "DP:0x%p/UID:%u/GameClientDispatch Destroy", this, m_dwUID);
}
void CGameClientDispatch::Connected()
{
}
void CGameClientDispatch::Disconnected()
{
if (0 != m_lpCharacter)
{
m_lpCharacter->SetDispatcher(0);
}
}
void CGameClientDispatch::Disconnect()
{
CloseSession();
}
bool CGameClientDispatch::DispatchPacket(PktBase* lpPktBase)
{
unsigned char cCmd = lpPktBase->GetCmd();
bool bHackCheck = true;
// 마지막으로 받은 패킷 시간 업데이트.
m_CheckPing.SetLastPingRecvTime(CPulse::GetInstance().GetLastTick());
switch (cCmd)
{
case CmdSysPing:
bHackCheck = m_CheckSpeedHack.CheckTimeUpdate(static_cast<PktSyP*>(lpPktBase)->m_dwTickTime);
return true;
case CmdCharAttack:
bHackCheck = m_CheckSpeedHack.CheckAttackReplay(static_cast<PktAt*>(lpPktBase));
break;
}
if (!bHackCheck)
{
ERRLOG3(g_Log, "DP:0x%p/IP:%s/UID:%10d/스피드핵 체크에 걸렸습니다. 접속을 끊습니다.",
this, GetRemoteAddr().get_addr_string(), m_dwUID);
}
else if (CXORCrypt::PAGE_VERSION != CXORCrypt::GetInstance().GetPageVer(lpPktBase->GetCodePage()))
{
// (클라이언트 -> 게임 서버)간 통신은 한 가지 코드 페이지만(현재는 1번)을 사용합니다.
ERRLOG3(g_Log, "DP:0x%p/IP:%s/UID:%d 잘못된 코드 페이지의 패킷입니다. 접속을 끊습니다.",
this, GetRemoteAddr().get_addr_string(), m_dwUID);
}
else
{
CGameClientDispatch::FnProcess fnProcess =
m_GameClientDispatchTable.GetDispatch(cCmd);
const char* szErrorString = 0;
if (0 == fnProcess)
{
szErrorString = "Unknown Gameserver Packet";
}
else if (!fnProcess(*this, lpPktBase))
{
szErrorString = "GameServer packet process failed.";
}
if (0 != szErrorString)
{
LogFailDispatch(*this, szErrorString, cCmd);
}
return true;
}
return false;
}
bool CGameClientDispatch::Dispatch()
{
unsigned long dwCurrentTime = timeGetTime();
// 핑 체크
if (0 != m_lpCharacter && // 캐릭터가 있어야 하고
0 == m_lpCharacter->GetAdminLevel() && // 운영자가 아니고
!m_CheckPing.CheckPing(dwCurrentTime)) // Ping체크에 실패하면
{
const int MAX_BUFFER = 256;
char szBuffer[MAX_BUFFER];
unsigned long dwPingCount = 0;
unsigned long dwLastPingRecvTime = 0;
unsigned long dwFirstCheckTime = 0;
unsigned long dwCID = m_lpCharacter->GetCID();
const char* szCharacterName = m_lpCharacter->GetCharacterName();
m_CheckPing.GetPingData(dwPingCount, dwLastPingRecvTime, dwFirstCheckTime);
_snprintf(szBuffer, MAX_BUFFER - 1,
"UID:%u/CID:%u/Name:%s/CurrentTime:%u/LastPingTime:%u/PingCount:%u/FirstCheckTime:%u/"
"PingCheck failed. disconnect now.",
m_dwUID, dwCID, szCharacterName, dwCurrentTime,
dwLastPingRecvTime, dwPingCount, dwFirstCheckTime);
LogErrorPacket(szBuffer, 0);
return false;
}
return CRylServerDispatch::Dispatch();
}
void CGameClientDispatch::ProcessTooManyPacket(CBufferQueue& bufferQueue)
{
if (0 != m_lpCharacter)
{
typedef std::map<unsigned char, unsigned long, std::greater<unsigned long>,
boost::fast_pool_allocator< std::pair<unsigned char, unsigned long> > > PacketStatistics;
const int MAX_BUFFER = 512;
char szBuffer[MAX_BUFFER];
PacketStatistics packetStatistics;
const SOCKADDR_IN& sockAddr = GetRemoteAddr().get_addr_in();
int nLength = _snprintf(szBuffer, MAX_BUFFER,
"/UID:%d/CID:0x%08x/Name:%s/IP:%15s/ProcessPkt:%4d/RemainPkt:%4d/",
m_lpCharacter->GetUID(), m_lpCharacter->GetCID(), m_lpCharacter->GetCharacterName(),
inet_ntoa(sockAddr.sin_addr), m_dwMaxProcessPacketPerPulse, bufferQueue.getBufferNum());
CBufferQueue tempQueue;
tempQueue.splice(bufferQueue);
const int DROP_PACKET_LIMIT = 20;
const int DROP_PACKET_MAX_LIMIT = 40;
bool bDropPacket = DROP_PACKET_MAX_LIMIT < tempQueue.getBufferNum();
// 패킷 통계를 구한다.
CBuffer* lpBuffer = tempQueue.getHead();
for(; 0 != lpBuffer; lpBuffer = lpBuffer->next())
{
unsigned char cCmd = reinterpret_cast<PktBase*>(lpBuffer->rd_ptr())->GetCmd();
++packetStatistics[cCmd];
}
const unsigned long dwMaxPrint = 5;
unsigned long dwPrinted = 0;
PktBase::CMDType aryDropCmd[dwMaxPrint];
PktBase::CMDType* lpDropCmdEnd = aryDropCmd;
std::pair<unsigned char, unsigned long> resultPair;
for(PacketStatistics::iterator itr = packetStatistics.begin();
itr != packetStatistics.end() && dwPrinted < dwMaxPrint; ++itr, ++dwPrinted)
{
resultPair = *itr;
nLength += _snprintf(szBuffer + nLength, MAX_BUFFER - nLength, "0x%02x:%5d/", resultPair.first, resultPair.second);
// 패킷이 한번에 얼마 이상 온 경우는 Drop할 리스트에 포함시킨다.
// 여기서는 Top 5에 속하는 패킷 중 DROP_PACKET_LIMIT 이상 되는 패킷만 버린다.
if(DROP_PACKET_LIMIT < resultPair.second)
{
*lpDropCmdEnd = resultPair.first;
++lpDropCmdEnd;
}
}
std::sort(aryDropCmd, lpDropCmdEnd);
ERRLOG0(g_Log, szBuffer);
for(;;)
{
lpBuffer = tempQueue.dequeue();
if(0 == lpBuffer)
{
break;
}
else
{
unsigned char cCmd = reinterpret_cast<PktBase*>(lpBuffer->rd_ptr())->GetCmd();
// 버려도 될 패킷이면 버린다.
if(bDropPacket && std::binary_search(aryDropCmd, lpDropCmdEnd, cCmd))
{
SAFE_RELEASE_BUFFER(lpBuffer);
}
else
{
bufferQueue.enqueue(lpBuffer);
}
}
}
}
}
bool LogFailDispatch(CGameClientDispatch& GameClientDispatch,
const char* szDetailText, const unsigned char cCmd)
{
unsigned long dwUID = GameClientDispatch.GetUID();
ERRLOG5(g_Log, "DP:0x%p/UID:%d/PacketCMD:0x%02x/IP:%15s/%s",
&GameClientDispatch, dwUID, cCmd,
GameClientDispatch.GetRemoteAddr().get_addr_string(), szDetailText);
return false;
}
unsigned long CGameClientDispatch::PopRequestKey()
{
unsigned long dwRequestKey = 0;
if (!m_DBRequestQueue.empty())
{
dwRequestKey = m_DBRequestQueue.front();
m_DBRequestQueue.pop_front();
}
unsigned long dwUID = 0;
unsigned long dwCID = 0;
if (0 != m_lpCharacter)
{
dwUID = m_lpCharacter->GetUID();
dwCID = m_lpCharacter->GetCID();
}
DETLOG7(g_Log, "UID:%u/CID:0x%p(0x%p)/IP:%15s/DP:0x%p/DUID:%u/RequestKey:%d/ "
"Pop RequestKey", dwUID, dwCID, m_lpCharacter,
GetRemoteAddr().get_addr_string(),
this, m_dwUID, dwRequestKey);
return dwRequestKey;
}
void CGameClientDispatch::PushRequestKey(unsigned long dwRequestKey)
{
unsigned long dwUID = 0;
unsigned long dwCID = 0;
if (0 != m_lpCharacter)
{
dwUID = m_lpCharacter->GetUID();
dwCID = m_lpCharacter->GetCID();
}
DETLOG7(g_Log, "UID:%u/CID:0x%p(0x%p)/IP:%15s/DP:0x%p/DUID:%u/RequestKey:%d/ "
"Push RequestKey", dwUID, dwCID, m_lpCharacter,
GetRemoteAddr().get_addr_string(),
this, m_dwUID, dwRequestKey);
m_DBRequestQueue.push_back(dwRequestKey);
}
bool CGameClientDispatch::GetAuthQuery(GG_AUTH_DATA** lppAuthData_Out)
{
unsigned long dwGGErrCode = m_CSAuth2.GetAuthQuery();
if (dwGGErrCode != ERROR_SUCCESS)
{
PrintGameGuardError(dwGGErrCode);
ERRLOG1(g_Log, "CID:0x%08x 인증 코드(2) GetAuthQuery 오류", m_lpCharacter->GetCID());
return false;
}
*lppAuthData_Out = &m_CSAuth2.m_AuthQuery;
return true;
}
bool CGameClientDispatch::CheckAuthAnswer(void)
{
unsigned long dwGGErrCode = m_CSAuth2.CheckAuthAnswer();
if (dwGGErrCode != ERROR_SUCCESS)
{
PrintGameGuardError(dwGGErrCode);
ERRLOG1(g_Log, "CID:0x%08x 인증 코드(2) CheckAuthAnswer 오류", m_lpCharacter->GetCID());
return false;
}
return true;
}
void CGameClientDispatch::PrintGameGuardError(void)
{
/* switch (m_CSAuth.PPGetLastError())
{
case 1:
ERRLOG1(g_Log, "CID:0x%08x 키가 일치하지 않습니다. "
"암호화되지 않은 패킷이거나, UserKey가 다른 클라이언트로부터 온 패킷일 수 있습니다.", m_lpCharacter->GetCID());
break;
case 2:
ERRLOG1(g_Log, "CID:0x%08x 시퀀스넘버가 최근의 패킷과 같습니다. "
"패킷 리플라이 공격이 원인일 수 있습니다.", m_lpCharacter->GetCID());
break;
case 3:
ERRLOG1(g_Log, "CID:0x%08x 시퀀스넘버가 비정상입니다. 서버와 클라이언트의 약속된 시퀀스넘버가 일치하지 않습니다. "
"네트웍 문제로 패킷 몇 개가 유실 되었을 수 있습니다. TCP 프로토콜에서는 거의 발생하지 않는 에러입니다.", m_lpCharacter->GetCID());
break;
case 4:
ERRLOG1(g_Log, "CID:0x%08x 패킷 CRC 체크에 실패했습니다. "
"패킷 에디터 등으로 고의로 패킷을 조작했을 수 있습니다.", m_lpCharacter->GetCID());
break;
}
*/
// edith 2009.08.11 게임가드 2.5 업그레이드
ERRLOG1(g_Log, "CID:0x%08x 제거된 게임가드 버젼을 사용하였습니다.", m_lpCharacter->GetCID());
}
void CGameClientDispatch::PrintGameGuardError(unsigned long dwGGErrCode)
{
const char* szErrorString = "알 수 없는 에러입니다";
switch (dwGGErrCode)
{
case ERROR_GGAUTH_FAIL_MEM_ALLOC:
szErrorString = "메모리 할당 실패";
break;
case ERROR_GGAUTH_FAIL_LOAD_DLL:
szErrorString = "ggauth.dll 로드 실패";
break;
case ERROR_GGAUTH_FAIL_GET_PROC:
szErrorString = "ggauth.dll의 Export 함수 가져오기 실패";
break;
case ERROR_GGAUTH_FAIL_BEFORE_INIT:
szErrorString = "ggauth.dll이 초기화되기 전에 Export 함수 호출하였음";
break;
case ERROR_GGAUTH_INVALID_PARAM:
szErrorString = "함수 호출 시 invalid parameter 전달";
break;
case ERROR_GGAUTH_NO_REPLY:
szErrorString = "인증 Query에 대한 클라이언트의 응답 없음";
break;
case ERROR_GGAUTH_INVALID_PROTOCOL_VERSION:
szErrorString = "클라이언트의 인증 프로토콜 버전 틀림";
break;
case ERROR_GGAUTH_INVALID_REPLY:
szErrorString = "인증 Query에 대한 클라이언트의 응답값이 틀림";
break;
}
DWORD dwCID = (0 != m_lpCharacter) ? m_lpCharacter->GetCID() : 0;
const int MAX_LOG = 256;
char szLog[MAX_LOG];
if (0 < _snprintf(szLog, MAX_LOG - 1, "CID:0x%08x %s : %d / "
"AQ.Index:0x%08x, AQ.V1:0x%08x, AQ.V2:0x%08x, AQ.V3:0x%08x, "
"AA.Index:0x%08x, AA.V1:0x%08x, AA.V2:0x%08x, AA.V3:0x%08x",
dwCID, szErrorString, dwGGErrCode,
m_CSAuth2.m_AuthQuery.dwIndex,
m_CSAuth2.m_AuthQuery.dwValue1,
m_CSAuth2.m_AuthQuery.dwValue2,
m_CSAuth2.m_AuthQuery.dwValue3,
m_CSAuth2.m_AuthAnswer.dwIndex,
m_CSAuth2.m_AuthAnswer.dwValue1,
m_CSAuth2.m_AuthAnswer.dwValue2,
m_CSAuth2.m_AuthAnswer.dwValue3))
{
ERRLOG0(g_Log, szLog);
}
}
void CGameClientDispatch::SetCharacter(CCharacter* lpCharacter)
{
m_lpCharacter = lpCharacter;
m_CheckSpeedHack.SetCharacter(lpCharacter);
}