385 lines
12 KiB
C++
385 lines
12 KiB
C++
#include "stdAfx.h"
|
|
#include ".\gmcmdmanager.h"
|
|
#include "User.h"
|
|
#include "UserManager.h"
|
|
//#include <GMList.h>
|
|
#include <PacketStruct_CW.h>
|
|
#include <ResultCode.h>
|
|
|
|
// 공지 위해
|
|
#include "BaseZone.h"
|
|
#include "Channel.h"
|
|
#include "ChannelManager.h"
|
|
|
|
GMCmdManager::GMCmdManager(void)
|
|
{
|
|
m_vecCmd.reserve( 10 );
|
|
m_GMString.Init();
|
|
}
|
|
|
|
GMCmdManager::~GMCmdManager(void)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
bool GMCmdManager::ParseCommand( User* pUser, const char* szCmd )
|
|
{
|
|
m_vecCmd.clear();
|
|
|
|
if( !IsGMUser( pUser ) )
|
|
{
|
|
// 이 경우는 크래킹이나 프로토콜 타입 버그일 가능성이 있다
|
|
MessageOut(eCRITICAL_LOG, "GM 아닌 유저가 공지 요청!!!(%s)", pUser->GetCharName().c_str());
|
|
return false;
|
|
}
|
|
|
|
if( !m_Parser.Parsing( szCmd, m_vecCmd ) )
|
|
return false;
|
|
|
|
if( !ProcessCommand( pUser, m_vecCmd ) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool GMCmdManager::ProcessCommand(User* gm_player, GM_CMD_STRING& gm_command)
|
|
{
|
|
bool is_success = false;
|
|
if (gm_command.size() > 0)
|
|
{
|
|
const STLX_TSTRING& gm_command_head = gm_command[0];
|
|
|
|
if (gm_command_head.compare(m_GMString.GetWorldNotice()) == 0) // 월드 공지
|
|
{
|
|
is_success = ProcessWorldNotice(gm_player, gm_command);
|
|
}
|
|
else if (gm_command_head.compare(m_GMString.GetChannelNotice()) == 0) // 채널 공지
|
|
{
|
|
is_success = ProcessChannelNotice(gm_player, gm_command);
|
|
}
|
|
else if (gm_command_head.compare(m_GMString.GetZoneNotice()) == 0) // 지역 공지
|
|
{
|
|
is_success = ProcessZoneNotice(gm_player, gm_command);
|
|
}
|
|
}
|
|
|
|
return is_success;
|
|
}
|
|
|
|
|
|
BOOL GMCmdManager::IsGMUser( User *pUser )
|
|
{
|
|
if( pUser->GetGMGrade() <= eGM_GRADE_BASE || pUser->GetGMGrade() >= eGM_GRADE_MAX )
|
|
{
|
|
MSG_CW_GM_STRING_CMD_NAK NakMsg;
|
|
NakMsg.m_byErrorCode = RC::RC_GM_ISNOT_GM; // GM이 아니다.
|
|
pUser->SendPacket( (BYTE*)&NakMsg, sizeof(NakMsg) );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// 월드 공지
|
|
bool GMCmdManager::ProcessWorldNotice( User* pUser, GM_CMD_STRING& vecCmd )
|
|
{
|
|
// TODO: f101210.2L, this logic is terrible...
|
|
|
|
// vecCmd 개수만큼 읽는다
|
|
TCHAR tszNoticeMsg[100]={0,};
|
|
WORD wCount=0;
|
|
|
|
for(DWORD i = 1; i<vecCmd.size(); i++)
|
|
{
|
|
// 공지 메시지 조립
|
|
if(wCount + vecCmd[i].size() > MAX_NOTICE_LEN )
|
|
{
|
|
// 공지 길이 이상은 잘린다
|
|
break;
|
|
}
|
|
_tcscat( tszNoticeMsg + wCount, vecCmd[i].c_str() );
|
|
wCount += static_cast<WORD>( vecCmd[i].size() );
|
|
tszNoticeMsg[wCount++] = ' ';
|
|
}
|
|
tszNoticeMsg[wCount]='\0';
|
|
|
|
MSG_CW_NOTICE_BRD noticeMsg;
|
|
noticeMsg.m_byCategory = CW_CHAT;
|
|
noticeMsg.m_byProtocol = CW_NOTICE_BRD;
|
|
noticeMsg.wLen = wCount;
|
|
memset(noticeMsg.szMsg, 0, sizeof(noticeMsg.szMsg));
|
|
memcpy( noticeMsg.szMsg, tszNoticeMsg, noticeMsg.wLen );
|
|
|
|
// 갖고 있는 모든 유저들에게 날린다
|
|
UserManager::Instance()->SendToAll( (BYTE*)¬iceMsg, noticeMsg.GetSize() );
|
|
|
|
char szNotice[MAX_NOTICE_LEN + 1];
|
|
ZeroMemory( szNotice, sizeof(szNotice) );
|
|
strncpy( szNotice, noticeMsg.szMsg, noticeMsg.wLen );
|
|
MessageOut(eCRITICAL_LOG, "-----------------------------<< 전체공지 >>-----------------------------" );
|
|
MessageOut(eCRITICAL_LOG, "%s(%u)", noticeMsg.szMsg, noticeMsg.wLen );
|
|
MessageOut(eCRITICAL_LOG, "------------------------------------------------------------------------" );
|
|
|
|
return true;
|
|
}
|
|
|
|
// 채널 공지
|
|
bool GMCmdManager::ProcessChannelNotice( User* pUser, GM_CMD_STRING& vecCmd )
|
|
{
|
|
// TODO: f101210.2L, this logic is terrible...
|
|
|
|
// vecCmd 개수만큼 읽는다
|
|
TCHAR tszNoticeMsg[100]={0,};
|
|
WORD wCount=0;
|
|
|
|
for(DWORD i = 1; i<vecCmd.size(); i++)
|
|
{
|
|
// 공지 메시지 조립
|
|
if(wCount + vecCmd[i].size() > MAX_NOTICE_LEN )
|
|
{
|
|
// 공지 길이 이상은 잘린다
|
|
break;
|
|
}
|
|
_tcscat( tszNoticeMsg + wCount, vecCmd[i].c_str() );
|
|
wCount += static_cast<WORD>( vecCmd[i].size() );
|
|
tszNoticeMsg[wCount++] = ' ';
|
|
}
|
|
tszNoticeMsg[wCount]='\0';
|
|
|
|
MSG_CW_NOTICE_BRD noticeMsg;
|
|
noticeMsg.m_byCategory = CW_CHAT;
|
|
noticeMsg.m_byProtocol = CW_NOTICE_BRD;
|
|
noticeMsg.wLen = wCount;
|
|
memset(noticeMsg.szMsg, 0, sizeof(noticeMsg.szMsg));
|
|
memcpy( noticeMsg.szMsg, tszNoticeMsg, noticeMsg.wLen );
|
|
|
|
// 해당 유저가 접속한 채널에만 날려준다
|
|
Channel *pChannel = ChannelManager::Instance()->GetChannel( pUser->GetChannelID() );
|
|
if(!pChannel)
|
|
{
|
|
// 사용자의 채널 ID가 틀렸다. 치명적인 버그
|
|
MessageOut( eCRITICAL_LOG, "사용자 %s의 채널 %u가 존재하지 않음!! 공지 실패!!", pUser->GetCharName().c_str(), pUser->GetChannelID() );
|
|
return false;
|
|
}
|
|
// 마을, 배틀존 모두 공지
|
|
pChannel->SendToAll( (BYTE*)¬iceMsg, noticeMsg.GetSize() );
|
|
|
|
char szNotice[MAX_NOTICE_LEN + 1];
|
|
ZeroMemory( szNotice, sizeof(szNotice) );
|
|
strncpy( szNotice, noticeMsg.szMsg, noticeMsg.wLen );
|
|
MessageOut(eCRITICAL_LOG, "----------------------------<< %d채널 공지 >>----------------------------", pUser->GetChannelID() );
|
|
MessageOut(eCRITICAL_LOG, "%s(%u)", noticeMsg.szMsg, noticeMsg.wLen );
|
|
MessageOut(eCRITICAL_LOG, "------------------------------------------------------------------------" );
|
|
|
|
return true;
|
|
}
|
|
|
|
// 지역 공지
|
|
bool GMCmdManager::ProcessZoneNotice( User* pUser, GM_CMD_STRING& vecCmd )
|
|
{
|
|
// TODO: f101210.2L, this logic is terrible...
|
|
|
|
// vecCmd 개수만큼 읽는다
|
|
TCHAR tszNoticeMsg[100]={0,};
|
|
WORD wCount=0;
|
|
|
|
for(DWORD i = 1; i<vecCmd.size(); i++)
|
|
{
|
|
// 공지 메시지 조립
|
|
if(wCount + vecCmd[i].size() > MAX_NOTICE_LEN )
|
|
{
|
|
// 공지 길이 이상은 잘린다
|
|
break;
|
|
}
|
|
_tcscat( tszNoticeMsg + wCount, vecCmd[i].c_str() );
|
|
wCount += static_cast<WORD>( vecCmd[i].size() );
|
|
tszNoticeMsg[wCount++] = ' ';
|
|
}
|
|
tszNoticeMsg[wCount]='\0';
|
|
|
|
MSG_CW_NOTICE_BRD noticeMsg;
|
|
noticeMsg.m_byCategory = CW_CHAT;
|
|
noticeMsg.m_byProtocol = CW_NOTICE_BRD;
|
|
noticeMsg.wLen = wCount;
|
|
memset(noticeMsg.szMsg, 0, sizeof(noticeMsg.szMsg));
|
|
memcpy( noticeMsg.szMsg, tszNoticeMsg, noticeMsg.wLen );
|
|
|
|
Channel *pChannel = ChannelManager::Instance()->GetChannel( pUser->GetChannelID() );
|
|
if(!pChannel)
|
|
{
|
|
// 사용자의 채널 ID가 틀렸다. 치명적인 버그
|
|
MessageOut( eCRITICAL_LOG, "사용자 %s의 채널 %u가 존재하지 않음!! 지역공지 실패!!", pUser->GetCharName().c_str(), pUser->GetChannelID() );
|
|
return false;
|
|
}
|
|
BaseZone *pZone = NULL;
|
|
|
|
pZone = pChannel->FindZone( pUser->GetZoneKey() );
|
|
|
|
if( !pZone )
|
|
{
|
|
// 사용자의 Zone ID가 틀렸다. 치명적인 버그
|
|
MessageOut( eCRITICAL_LOG, "사용자 %s의 마을 %u가 존재하지 않음!! 공지 실패!!", pUser->GetCharName().c_str(),
|
|
pUser->GetZoneKey() );
|
|
return false;
|
|
}
|
|
pZone->Send( (BYTE*)¬iceMsg, noticeMsg.GetSize() );
|
|
|
|
char szNotice[MAX_NOTICE_LEN + 1];
|
|
ZeroMemory( szNotice, sizeof(szNotice) );
|
|
strncpy( szNotice, noticeMsg.szMsg, vecCmd.begin()->size() );
|
|
MessageOut(eCRITICAL_LOG, "---------------------------<< %u채널 %uZone공지[ZT:%u] >>-------------------------",
|
|
pUser->GetChannelID(),
|
|
pUser->GetZoneKey(), pUser->GetStatus() );
|
|
MessageOut(eCRITICAL_LOG, "%s(%u)", noticeMsg.szMsg, noticeMsg.wLen );
|
|
MessageOut(eCRITICAL_LOG, "------------------------------------------------------------------------" );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GMCmdManager::ProcessNoticeType(User *pUser, eNOTICE_TYPE eType, TCHAR *ptszNoticeMsg)
|
|
{
|
|
switch(eType)
|
|
{
|
|
case eNOTICE_WORLD:
|
|
{
|
|
ProcessWorldNotice(pUser, ptszNoticeMsg);
|
|
return true;
|
|
}
|
|
break;
|
|
case eNOTICE_CHANNEL:
|
|
{
|
|
ProcessChannelNotice(pUser, ptszNoticeMsg);
|
|
return true;
|
|
}
|
|
break;
|
|
case eNOTICE_ZONE:
|
|
{
|
|
ProcessZoneNotice(pUser, ptszNoticeMsg);
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
VOID GMCmdManager::ProcessWorldNotice(User *pUser, TCHAR *ptszNoticeMsg)
|
|
{
|
|
MSG_CW_NOTICE_BRD msgBRD;
|
|
|
|
msgBRD.m_byCategory = CW_CHAT;
|
|
msgBRD.m_byProtocol = CW_NOTICE_BRD;
|
|
msgBRD.m_byRed = 236;
|
|
msgBRD.m_byGreen = 96;
|
|
msgBRD.m_byBlue = 12;
|
|
// CHANGES: f101210.2L, check boundary
|
|
if (size_t str_len = strlen(ptszNoticeMsg) + 1)
|
|
{
|
|
// NOTE: always true, because wLen need consider with null-terminated position
|
|
strncpy(msgBRD.szMsg, ptszNoticeMsg, _countof(msgBRD.szMsg));
|
|
msgBRD.szMsg[_countof(msgBRD.szMsg) - 1] = '\0';
|
|
str_len = min(_countof(msgBRD.szMsg), str_len);
|
|
msgBRD.wLen = static_cast<uint16_t>(str_len);
|
|
}
|
|
|
|
// 갖고 있는 모든 유저들에게 날린다
|
|
UserManager::Instance()->SendToAll( (BYTE*)&msgBRD, msgBRD.GetSize() );
|
|
|
|
char szNotice[MAX_NOTICE_LEN + 1];
|
|
ZeroMemory( szNotice, sizeof(szNotice) );
|
|
strncpy( szNotice, msgBRD.szMsg, msgBRD.wLen );
|
|
MessageOut(eCRITICAL_LOG, "-----------------------------<< 전체공지 >>-----------------------------" );
|
|
MessageOut(eCRITICAL_LOG, "%s(%u)", msgBRD.szMsg, msgBRD.wLen );
|
|
MessageOut(eCRITICAL_LOG, "------------------------------------------------------------------------" );
|
|
}
|
|
|
|
VOID GMCmdManager::ProcessChannelNotice(User *pUser, TCHAR *ptszNoticeMsg)
|
|
{
|
|
MSG_CW_NOTICE_BRD msgBRD;
|
|
|
|
msgBRD.m_byCategory = CW_CHAT;
|
|
msgBRD.m_byProtocol = CW_NOTICE_BRD;
|
|
msgBRD.m_byRed = 236;
|
|
msgBRD.m_byGreen = 96;
|
|
msgBRD.m_byBlue = 12;
|
|
// CHANGES: f101210.2L, check boundary
|
|
if (size_t str_len = strlen(ptszNoticeMsg) + 1)
|
|
{
|
|
// NOTE: always true, because wLen need consider with null-terminated position
|
|
strncpy(msgBRD.szMsg, ptszNoticeMsg, _countof(msgBRD.szMsg));
|
|
msgBRD.szMsg[_countof(msgBRD.szMsg) - 1] = '\0';
|
|
str_len = min(_countof(msgBRD.szMsg), str_len);
|
|
msgBRD.wLen = static_cast<uint16_t>(str_len);
|
|
}
|
|
|
|
// 해당 유저가 접속한 채널에만 날려준다
|
|
Channel *pChannel = ChannelManager::Instance()->GetChannel(pUser->GetChannelID());
|
|
if(!pChannel)
|
|
{
|
|
// 사용자의 채널 ID가 틀렸다. 치명적인 버그
|
|
MessageOut( eCRITICAL_LOG, "사용자 %s의 채널 %u가 존재하지 않음!! 공지 실패!!", pUser->GetCharName().c_str(), pUser->GetChannelID() );
|
|
return;
|
|
}
|
|
// 마을, 배틀존 모두 공지
|
|
pChannel->SendToAll( (BYTE*)&msgBRD, msgBRD.GetSize() );
|
|
|
|
char szNotice[MAX_NOTICE_LEN + 1];
|
|
ZeroMemory( szNotice, sizeof(szNotice) );
|
|
strncpy( szNotice, msgBRD.szMsg, msgBRD.wLen );
|
|
MessageOut(eCRITICAL_LOG, "----------------------------<< %d채널 공지 >>----------------------------", pUser->GetChannelID() );
|
|
MessageOut(eCRITICAL_LOG, "%s(%u)", msgBRD.szMsg, msgBRD.wLen );
|
|
MessageOut(eCRITICAL_LOG, "------------------------------------------------------------------------" );
|
|
}
|
|
|
|
VOID GMCmdManager::ProcessZoneNotice(User *pUser, TCHAR *ptszNoticeMsg)
|
|
{
|
|
MSG_CW_NOTICE_BRD msgBRD;
|
|
|
|
msgBRD.m_byCategory = CW_CHAT;
|
|
msgBRD.m_byProtocol = CW_NOTICE_BRD;
|
|
msgBRD.m_byRed = 236;
|
|
msgBRD.m_byGreen = 96;
|
|
msgBRD.m_byBlue = 12;
|
|
// CHANGES: f101210.2L, check boundary
|
|
if (size_t str_len = strlen(ptszNoticeMsg) + 1)
|
|
{
|
|
// NOTE: always true, because wLen need consider with null-terminated position
|
|
strncpy(msgBRD.szMsg, ptszNoticeMsg, _countof(msgBRD.szMsg));
|
|
msgBRD.szMsg[_countof(msgBRD.szMsg) - 1] = '\0';
|
|
str_len = min(_countof(msgBRD.szMsg), str_len);
|
|
msgBRD.wLen = static_cast<uint16_t>(str_len);
|
|
}
|
|
|
|
Channel *pChannel = ChannelManager::Instance()->GetChannel(pUser->GetChannelID());
|
|
if(!pChannel)
|
|
{
|
|
// 사용자의 채널 ID가 틀렸다. 치명적인 버그
|
|
MessageOut(eCRITICAL_LOG, "사용자 %s의 채널 %u가 존재하지 않음!! 지역공지 실패!!", pUser->GetCharName().c_str(), pUser->GetChannelID());
|
|
return;
|
|
}
|
|
|
|
BaseZone *pZone = NULL;
|
|
|
|
pZone = pChannel->FindZone( pUser->GetZoneKey() );
|
|
if( !pZone )
|
|
{
|
|
// 사용자의 Zone ID가 틀렸다. 치명적인 버그
|
|
MessageOut( eCRITICAL_LOG, "사용자 %s의 마을 %u가 존재하지 않음!! 공지 실패!!", pUser->GetCharName().c_str(),
|
|
pUser->GetZoneKey() );
|
|
return;
|
|
}
|
|
pZone->Send( (BYTE*)&msgBRD, msgBRD.GetSize() );
|
|
|
|
char szNotice[MAX_NOTICE_LEN + 1];
|
|
ZeroMemory( szNotice, sizeof(szNotice) );
|
|
strncpy( szNotice, msgBRD.szMsg, msgBRD.wLen );
|
|
MessageOut(eCRITICAL_LOG, "---------------------------<< %u채널 %uZone공지[ZT:%u] >>-------------------------",
|
|
pUser->GetChannelID(),
|
|
pUser->GetZoneKey(), pUser->GetStatus() );
|
|
MessageOut(eCRITICAL_LOG, "%s(%u)", msgBRD.szMsg, msgBRD.wLen );
|
|
MessageOut(eCRITICAL_LOG, "------------------------------------------------------------------------" );
|
|
}
|