Files
Client/Server/ManageTool/MonitoringTool/ChattingPage.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

912 lines
27 KiB
C++

// ChattingPage.cpp : 구현 파일입니다.
//
#include "stdafx.h"
#include "MonitoringTool.h"
#include "MonitoringToolDlg.h"
#include "ChattingPage.h"
#include "GlobalFunc.h"
#include "ChatServerEventHandler.h"
#include "MonitoringToolSetup.h"
#include "MonitoringToolLog.h"
#include "MonitoringToolSetup.h"
#include "LoginDlg.h"
#include "WhisperDlg.h"
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <UserManage/UserStatistics.h>
#include <Utility/Setup/ServerSetup.h>
#include <Log/ServerLog.h>
#include ".\chattingpage.h"
// CChattingPage 대화 상자입니다.
IMPLEMENT_DYNAMIC(CChattingPage, CPropertyPage)
CChattingPage::CChattingPage()
: CPropertyPage(CChattingPage::IDD)
, m_bAutoScroll(TRUE)
, m_sChatMessageLines(0)
, m_nMaxGroup(0)
, m_dwAccountDlgID(0)
, m_usLocalLang(0xFFFF)
{
m_lpWhisperDlg = NULL;
theApp.RegisterWindow(IDD_CHATTINGPAGE, static_cast<CWnd*>(this));
}
CChattingPage::~CChattingPage()
{
theApp.RemoveWindow(IDD_CHATTINGPAGE);
}
void CChattingPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CHATMONITOR_LIST, m_ctrlChatMonitorList);
DDX_Control(pDX, IDC_SERVERGROUP_LIST, m_ctrlServerGroupCbList);
DDX_Control(pDX, IDC_CHATTYPE_LIST, m_ctrlChatTypeList);
DDX_Control(pDX, IDC_CONNECTION_LIST, m_ctrlConnectionList);
DDX_Control(pDX, IDC_CHATTYPE_CB, m_ctrlChatTypeCb);
DDX_Control(pDX, IDC_SERVERGROUP_CB, m_ctrlServerGroupCb);
DDX_Check(pDX, IDC_AUTOSCROLL_CHK, m_bAutoScroll);
DDX_Text(pDX, IDC_CHATLINES_EDIT, m_sChatMessageLines);
DDX_Control(pDX, IDC_USERSTAT_LIST, m_ctrlUserStatList);
}
BEGIN_MESSAGE_MAP(CChattingPage, CPropertyPage)
ON_LBN_SELCHANGE(IDC_CHATTYPE_LIST, OnLbnSelchangeOpt)
ON_LBN_SELCHANGE(IDC_SERVERGROUP_LIST, OnLbnSelchangeOpt)
ON_BN_CLICKED(IDC_CHATMSG_SEND_BTN, OnBnClickedChatmsgSendBtn)
ON_BN_CLICKED(IDC_AUTOSCROLL_CHK, OnBnClickedAutoscrollChk)
ON_BN_CLICKED(IDC_DELETECHATMSG_BTN, OnBnClickedDeletechatmsgBtn)
ON_BN_CLICKED(IDC_CHATLOGFLUSH_BTN, OnBnClickedChatlogflushBtn)
ON_BN_CLICKED(IDC_AUTH_MANAGER_BTN, OnBnClickedAuthManagerBtn)
ON_BN_CLICKED(IDC_FLUSH_STATLOG_BTN, OnBnClickedFlushStatlogBtn)
ON_LBN_DBLCLK(IDC_CHATMONITOR_LIST, OnLbnDblclkChatmonitorList)
ON_BN_CLICKED(IDC_CALL_WHISPER_DLG, OnBnClickedCallWhisperDlg)
ON_BN_CLICKED(IDC_GMLOGINED_CHK, OnBnClickedGmloginedChk)
ON_BN_CLICKED(IDC_LANGTYPE_CHK, OnBnClickedLangtypeChk)
ON_WM_SIZE()
END_MESSAGE_MAP()
// CChattingPage 메시지 처리기입니다.
BOOL CChattingPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const unsigned int nMaxZone = Setup.GetInt(_T("ZONE_INFO"), _T("ZONE_NUM"));
m_nMaxGroup = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
unsigned int nMaxChannel = Setup.GetInt(_T("CHANNEL_INFO"), _T("CHANNEL_NUM"));
SetServerListBox(m_ctrlServerGroupCbList);
SetChatTypeListBox(m_ctrlChatTypeList);
SetSendChatTypeCombo(m_ctrlChatTypeCb);
SetServerGroupCombo(m_ctrlServerGroupCb);
for(int nIndex = 0; nIndex < m_ctrlServerGroupCbList.GetCount(); ++nIndex)
m_ctrlServerGroupCbList.SetSel(nIndex);
for(int nIndex = 0; nIndex < m_ctrlChatTypeList.GetCount(); ++nIndex)
m_ctrlChatTypeList.SetSel(nIndex);
char szKey[256];
CString strFormat;
m_strLoginedName = "";
// 동접 정보 리스트 초기화
m_ctrlUserStatList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_FLATSB);
m_ctrlUserStatList.InsertColumn(0, _T("Z:00 C:00"), LVCFMT_CENTER, 73);
for(unsigned int nIndex = 0; nIndex < m_nMaxGroup; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_NAME_%02d", nIndex);
strFormat.Format(_T("%s"), Setup.GetString(_T("SERVER_GROUP_INFO"), szKey, _T("?")));
m_ctrlUserStatList.InsertColumn(nIndex + 1, strFormat, LVCFMT_RIGHT, 61);
}
SetDlgItemText(IDC_STRING001_STATIC, GetMyINIString("LOCAL_STRING", "STRING_001"));
SetDlgItemText(IDC_STRING002_STATIC, GetMyINIString("LOCAL_STRING", "STRING_002"));
SetDlgItemText(IDC_AUTOSCROLL_CHK, GetMyINIString("LOCAL_STRING", "STRING_003"));
SetDlgItemText(IDC_CHATLOGFLUSH_BTN, GetMyINIString("LOCAL_STRING", "STRING_004"));
SetDlgItemText(IDC_DELETECHATMSG_BTN, GetMyINIString("LOCAL_STRING", "STRING_005"));
SetDlgItemText(IDC_STRING006_STATIC, GetMyINIString("LOCAL_STRING", "STRING_006"));
SetDlgItemText(IDC_STRING007_STATIC, GetMyINIString("LOCAL_STRING", "STRING_007"));
SetDlgItemText(IDC_STRING007_STATIC2, GetMyINIString("LOCAL_STRING", "STRING_007"));
SetDlgItemText(IDC_STRING008_STATIC, GetMyINIString("LOCAL_STRING", "STRING_008"));
SetDlgItemText(IDC_STRING008_STATIC2, GetMyINIString("LOCAL_STRING", "STRING_008"));
SetDlgItemText(IDC_STRING009_STATIC, GetMyINIString("LOCAL_STRING", "STRING_009"));
SetDlgItemText(IDC_STRING010_STATIC, GetMyINIString("LOCAL_STRING", "STRING_010"));
SetDlgItemText(IDC_FLUSH_STATLOG_BTN, GetMyINIString("LOCAL_STRING", "STRING_011"));
SetDlgItemText(IDC_STRING012_STATIC, GetMyINIString("LOCAL_STRING", "STRING_012"));
SetDlgItemText(IDC_AUTH_MANAGER_BTN, GetMyINIString("LOCAL_STRING", "STRING_013"));
SetDlgItemText(IDC_STRING016_STATIC, GetMyINIString("LOCAL_STRING", "STRING_016"));
SetDlgItemText(IDC_CHATMSG_SEND_BTN, GetMyINIString("LOCAL_STRING", "STRING_017"));
SetDlgItemText(IDC_CALL_WHISPER_DLG, GetMyINIString("LOCAL_STRING", "STRING_023"));
SetDlgItemText(IDC_LOGINEDNAME_STATIC, GetMyINIString("LOCAL_STRING", "STRING_047"));
SetDlgItemText(IDC_GMLOGINED_CHK, GetMyINIString("LOCAL_STRING", "STRING_048"));
SetDlgItemText(IDC_LANGTYPE_CHK, GetMyINIString("LOCAL_STRING", "STRING_049"));
// 동접로그 파일에 컬럼명 명시
CString strColumnName;
strColumnName.Format(_T("WriteTime\tGroupIndex"));
for (unsigned int nZone = 0; nZone < nMaxZone; ++nZone)
{
_snprintf(szKey, MAX_PATH, _T("ZONE_INDEX_%02d"), nZone);
for (unsigned int nCH = 0; nCH < nMaxChannel; ++nCH)
{
strColumnName.AppendFormat(_T("\tZ:%02d C:%02d"),
Setup.GetInt(_T("ZONE_INFO"), szKey, 100), nCH + 1);
}
}
strColumnName.Append(_T("\r\n"));
CMonitoringToolLog::GetInstance().WriteUserStatLog(strColumnName);
return TRUE;
}
const unsigned short ALLOW_LETTER_NUM = 33;
const char AllowLetters[ALLOW_LETTER_NUM] = {
' ', '`', '~', '!', '@', '#', '$', '%', '^', '&',
'*', '(', ')', '-', '=', '_', '+', '{', '}', '|',
'[', ']', '\\', ';', '\'', ':', '\"', '<', '>', '?',
',', '.', '/'
};
BOOL CChattingPage::CheckCharSet(CHAR* str, int Len)
{
int ACount = 0;
// 영어만 입력가능
for(unsigned short LCount = 0; LCount < Len; LCount++)
{
// 2바이트 검출
if((str[LCount] & 0x80))
return TRUE;
// 영문자 허용
if((str[LCount] >= 'A' && str[LCount] <= 'Z') ||
(str[LCount] >= 'a' && str[LCount] <= 'z'))
{
continue;
}
// 숫자 허용
if(str[LCount] >= '0' && str[LCount] <= '9')
{
continue;
}
// 특수 기호 부분 허용
for(ACount = 0; ACount < ALLOW_LETTER_NUM; ACount++)
{
if(str[LCount] == AllowLetters[ACount])
{
break;
}
}
if(ACount == ALLOW_LETTER_NUM)
{
return TRUE;
}
}
return FALSE;
}
BOOL CChattingPage::CheckAisaLang(unsigned short usLang)
{
switch(usLang)
{
case LANG_JAPANESE: // 일본어
case LANG_KOREAN: // 한국어
case LANG_CHINESE: // 중국어
case LANG_THAI: // 태국어
return TRUE;
}
return FALSE;
}
void CChattingPage::AddLineToChatMonitorList(unsigned char cChatType, unsigned short usLang, char* szMsg, bool bIsCall)
{
CXListBox::Color cBackColor = CXListBox::BackColor;
CXListBox::Color cMessageColor = CXListBox::ChatNormal;
if (false == bIsCall)
{
switch(cChatType)
{
case PktChat::NORMAL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PktChat::PARTY:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatParty;
break;
case PktChat::FRIEND:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatFriend;
break;
case PktChat::GUILD:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatGuild;
break;
case PktChat::CLIENT_LOG:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PktChat::STALL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatStall;
break;
case PktChat::SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatShout;
break;
case PktChat::ADMIN_NORMAL_CHAT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminNormal;
break;
case PktChat::ADMIN_SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case PktChat::WHISPER:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatWhisper;
break;
case PktChat::TRADE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatTrade;
break;
case PktChat::NOTICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNotice;
break;
case PktChat::DICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case PktChat::GMREPORT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::GMReport;
break;
}
}
else
{
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::Call;
}
if (m_ctrlChatMonitorList.GetCount() > 5000)
{
//m_ctrlChatMonitorList.DeleteString(0);
m_ctrlChatMonitorList.ResetContent();
}
#ifdef NO_WHISPER
if(cChatType != PktChat::WHISPER)
#endif
{
m_sChatMessageLines = (unsigned long)m_ctrlChatMonitorList.GetCount();
m_ctrlChatMonitorList.AddLine(cMessageColor, cBackColor, szMsg, m_bAutoScroll);
}
UpdateData(false);
}
/// \brief 채팅패킷을 파싱하여 모니터링 스크린(m_ctrlChatMonitorList)에 출력
/// \param lpChatData 채팅 패킷
/// \param bIsCall 유저가 모니터링툴을 사용중인 유저에게 메세지를 보냈는지 여부
/// \note 모니터링 스크린의 특정라인을 더블클릭하면 대화창이 뜨도록하기 위해 SetItemData로 UID를 셋팅
void CChattingPage::ParseChatData(ChatToolPkt::ChatDataSend* lpChatData, bool bIsCall, bool bGMSender)
{
const int MAX_CHAT_LEN = 1024;
char strChatMsg[MAX_CHAT_LEN];
char strRecvMsg[UCHAR_MAX * 2];
char strRace[4][4] = {"N/A", "H", "A", "N/A"};
SERVER_ID serverID;
serverID.dwID = lpChatData->m_dwServerID;
if (0 != lpChatData)
{
time_t tCurrent = time(NULL);
struct tm tmCurrent = *localtime(&tCurrent);
memcpy(strRecvMsg, reinterpret_cast<char*>(lpChatData + 1), lpChatData->m_cChatMsgLen);
strRecvMsg[lpChatData->m_cChatMsgLen] = 0;
if (PktChat::WHISPER == lpChatData->m_cChatType)
{
/////////////////////////////////////////////////////////////////////////////////////////////
// 지엠한테 귓속말이 오면 강제로 귓속말을 처리하게 한다.
if(bIsCall)
{
unsigned long dwUID = lpChatData->m_dwUID;
unsigned long dwCID = lpChatData->m_dwCID;
CWhisperDlg::WhisperDlgInfo stInfo;
ZeroMemory(&stInfo, sizeof(CWhisperDlg::WhisperDlgInfo));
stInfo.m_nDlgType = CWhisperDlg::WhisperDlgInfo::DLG_TYPE::WHISPER_TYPE_CLK;
stInfo.m_dwUID = dwUID;
stInfo.m_dwCID = dwCID;
stInfo.m_cRace = lpChatData->m_cRace;
strncpy(stInfo.m_szServerName, theApp.GetServerName((unsigned int)serverID.GetGroup()), CWhisperDlg::WhisperDlgInfo::MAX_NAME);
if(!bGMSender)
strncpy(stInfo.m_szCharName, lpChatData->m_szSenderName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
else
strncpy(stInfo.m_szCharName, lpChatData->m_szTargetName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
// 이미 창이 띄워져 있는지 체크
WhisperDlgMap::iterator find = m_WhisperDlgMap.find(dwUID);
if (find != m_WhisperDlgMap.end())
{
(find->second)->SetFocus();
}
else
{
// 새 대화 모달리스 창 생성
m_lpWhisperDlg = new CWhisperDlg(this, stInfo);
m_lpWhisperDlg->Create(IDD_WHISPERDLG,this);
m_lpWhisperDlg->ShowWindow(SW_SHOW);
// 맵에 등록
m_WhisperDlgMap.insert(WhisperDlgMap::value_type(dwUID, m_lpWhisperDlg));
m_lpWhisperDlg->ParseChatData(lpChatData);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d][R:%s] %s : %s (To: %s)",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min, strRace[lpChatData->m_cRace],
lpChatData->m_szSenderName, strRecvMsg, lpChatData->m_szTargetName);
}
else if (PktChat::DICE == lpChatData->m_cChatType)
{
char strID[32];
int iMax, iCur;
sscanf(strRecvMsg, "%s %d %d", strID, &iMax, &iCur);
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d][R:%s] %s 님이 %d 주사위를 굴려 %d 가 나왔습니다.",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min, strRace[lpChatData->m_cRace], strID, iMax, iCur);
}
else
{
_snprintf(strChatMsg, MAX_CHAT_LEN - 1, "%s\t [Z:%02d/C:%d/L:%04x][%02d:%02d][R:%s] %s",
theApp.GetServerName((unsigned int)serverID.GetGroup()),
serverID.GetZone(), serverID.GetChannel(), lpChatData->m_usLang, tmCurrent.tm_hour, tmCurrent.tm_min, strRace[lpChatData->m_cRace], strRecvMsg);
}
if(m_usLocalLang != 0xFFFF)
{
if(CheckCharSet(strRecvMsg, strlen(strRecvMsg)) // 멀티바이트 문자이고
&& CheckAisaLang(lpChatData->m_usLang)
&& lpChatData->m_usLang != m_usLocalLang) // 내 컴퓨터의 언어와 동일하지 않으면
{
return;
}
}
AddLineToChatMonitorList(lpChatData->m_cChatType, lpChatData->m_usLang, strChatMsg, bIsCall);
m_ctrlChatMonitorList.SetItemData(m_ctrlChatMonitorList.GetCount() - 1, lpChatData->m_dwUID);
m_CharacterID[lpChatData->m_dwUID] = lpChatData->m_dwCID;
}
}
void CChattingPage::OnLbnSelchangeOpt()
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
const char* szSection = _T("SERVER_GROUP_INFO");
char szKey[MAX_PATH];
// 채팅 필터링 옵션에 변화가 생겼을때의 이벤트 처리
// 1. 필터링 옵션 배열 초기화 : 초기값은 기본 옵션 모두 ON!
unsigned char szOption[ChatToolPkt::ChatOption::MAX_OPTION];
std::fill_n(szOption, int(ChatToolPkt::ChatOption::MAX_OPTION), 1);
// 2. 채팅 타입 별 필터링 : 선택되어 있는 옵션만 ON
// (단, 리스트 박스 인덱스는 DO_LISTEN(0)이 빠져 있으므로 패킷에 정의된 옵션 인덱스보다 1이 작음)
for(int nCurIndex = 0; nCurIndex < m_ctrlChatTypeList.GetCount(); ++nCurIndex)
{
if (0 != m_ctrlChatTypeList.GetSel(nCurIndex))
{
szOption[nCurIndex + 1] = 1; // 선택된 인덱스의 옵션 ON
}
else
{
szOption[nCurIndex + 1] = 0; // 선택되지 않은 인덱스의 옵션 OFF
}
}
// 3. 서버군 별 필터링 : 선택된 서버군과 선택되지 않은 서버군의 DO_LISTEN 옵션을 조정하여 전송!
unsigned int nMaxGroup = Setup.GetInt(szSection, "SERVER_GROUP_NUM");
for(unsigned int nIndex = 0; nIndex < nMaxGroup; ++nIndex)
{
_snprintf(szKey, MAX_PATH, _T("SERVER_GROUP_INDEX_%02d"), nIndex);
unsigned int nGroupIndex = Setup.GetInt(szSection, szKey, 100);
int nFind = m_ctrlServerGroupCbList.FindString(-1, theApp.GetServerName(nGroupIndex));
if (0 != m_ctrlServerGroupCbList.GetSel(nFind))
{
szOption[ChatToolPkt::ChatOption::DO_LISTEN] = 1; // 선택된 서버군 DO LISTEN
}
else
{
szOption[ChatToolPkt::ChatOption::DO_LISTEN] = 0; // 선택되지 않은 서버군 DO NOT LISTEN
}
if (NULL != theApp.GetChatServerHandler(nGroupIndex))
{
ClientNet::CChatServerEventHandler::SendChatOptPkt(
nGroupIndex, szOption, ChatToolPkt::ChatOption::MAX_OPTION);
}
}
}
void CChattingPage::OnBnClickedChatmsgSendBtn()
{
if (false == theApp.IsAuthorized())
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_044"));
return;
}
CString strServerName, strChatType, strMsg;
unsigned int nChatType;
// 보내는 메세지
GetDlgItemText(IDC_CHATMSG_EDIT, strMsg);
if(strMsg.GetLength() == 0)
return;
strMsg.Append(_T(" ")); // 맨 뒤 문자 깨지는거 방지 (귀찮;)
// 강제 귓속말 보내기 정보.
if(strncmp("/s ", strMsg.GetString(), 3) == 0)
{
// 강제로 귓말로 날렸다.
CString strGMName;
strGMName = theApp.GetLoginedName(); // GM명
char strTarget[32];
sscanf(strMsg.GetString(), "/s %s ", strTarget);
int Len = (int)strlen(strTarget)+4;
strMsg.Delete(0, Len);
unsigned long dwDlgID = GetAccountDlgID();
bool IsSended = false;
char szKey[256];
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
unsigned int nMaxGroupNum = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
for(int nIndex = 0; nIndex < (int)nMaxGroupNum; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
IsSended = ClientNet::CChatServerEventHandler::SendChatReqPkt(
nServerGroup, PktChat::WHISPER,
ChatToolPkt::TARGET_CHARNAME, 0, 0, strGMName, strTarget, strMsg);
}
if(!IsSended)
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_026"));
return;
}
if (CB_ERR == m_ctrlChatTypeCb.GetCurSel()
|| CB_ERR == m_ctrlServerGroupCb.GetCurSel())
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_025"));
return;
}
// 서버 명
m_ctrlServerGroupCb.GetLBText(m_ctrlServerGroupCb.GetCurSel(), strServerName);
// 채팅 타입
m_ctrlChatTypeCb.GetLBText(m_ctrlChatTypeCb.GetCurSel(), strChatType);
nChatType = GetChatTypeIndex(strChatType);
if (true == ClientNet::CChatServerEventHandler::SendChatReqPkt(
theApp.GetServerIndex(strServerName), nChatType,
ChatToolPkt::TARGET_CHARNAME, 0, 0, theApp.GetLoginedName(), _T(""), strMsg))
{
SetDlgItemText(IDC_CHATMSG_EDIT, _T(""));
}
else
{
// 보내기 실패 에러 메세지
}
}
void CChattingPage::OnBnClickedAutoscrollChk()
{
if(m_bAutoScroll)
{
m_bAutoScroll = FALSE;
}
else
{
m_bAutoScroll = TRUE;
}
}
void CChattingPage::OnBnClickedDeletechatmsgBtn()
{
m_ctrlChatMonitorList.ResetContent();
}
void CChattingPage::OnBnClickedChatlogflushBtn()
{
CMonitoringToolLog::GetInstance().FlushChatLog();
}
void CChattingPage::SetManagerServerConnection()
{
CString strConnection;
if (NULL != theApp.GetManagerHandler())
{
strConnection = GetMyINIString("LOCAL_STRING", "STRING_027");
}
else
{
strConnection = GetMyINIString("LOCAL_STRING", "STRING_028");
}
SetDlgItemText(IDC_MANAGERSERVER_CON_EDIT, strConnection);
}
void CChattingPage::OnBnClickedAuthManagerBtn()
{
CLoginDlg dlg(CLoginDlg::MANAGER_SERVER);
dlg.DoModal();
}
void CChattingPage::SetUserStat()
{
m_ctrlUserStatList.DeleteAllItems();
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
unsigned int nMaxGroup = Setup.GetInt(_T("SERVER_GROUP_INFO"), _T("SERVER_GROUP_NUM"));
unsigned int nMaxZone = Setup.GetInt(_T("ZONE_INFO"), _T("ZONE_NUM"));
unsigned int nMaxChannel = Setup.GetInt(_T("CHANNEL_INFO"), _T("CHANNEL_NUM"));
CString strKey;
CString strUserNum;
CString strRowName;
for (unsigned int nZone = 0; nZone < nMaxZone; ++nZone)
{
for (unsigned int nCH = 0; nCH < nMaxChannel; ++nCH)
{
strKey.Format(_T("ZONE_INDEX_%02d"), nZone);
unsigned int nZoneIndex = Setup.GetInt(_T("ZONE_INFO"), strKey, 100);
strRowName.Format(_T("Z:%02d C:%02d"), nZoneIndex, nCH + 1);
m_ctrlUserStatList.InsertItem((nZone * nMaxChannel) + nCH, strRowName);
for (unsigned int nGroup = 0; nGroup < nMaxGroup; ++nGroup)
{
strKey.Format(_T("SERVER_GROUP_INDEX_%02d"), nGroup);
unsigned int nGroupIndex = Setup.GetInt(_T("SERVER_GROUP_INFO"), strKey, 100);
SERVER_ID serverID;
serverID.dwID = 0;
serverID.sID.ID = nZoneIndex;
serverID.sID.Group = nGroupIndex;
serverID.sID.Type = CServerSetup::GameServer;
serverID.sID.Channel = nCH;
strUserNum.Format(_T("%d"), CUserStatistics::GetInstance().GetUserNum(serverID.dwID));
m_ctrlUserStatList.SetItemText((nZone * nMaxChannel) + nCH, nGroup + 1, strUserNum);
}
}
}
unsigned int nTotalUserNum = 0;
int nRow = m_ctrlUserStatList.GetItemCount();
m_ctrlUserStatList.InsertItem(nRow, _T("SUM"));
for (unsigned int nGroup = 0; nGroup < nMaxGroup; ++nGroup)
{
strKey.Format(_T("SERVER_GROUP_INDEX_%02d"), nGroup);
unsigned int nGroupIndex = Setup.GetInt(_T("SERVER_GROUP_INFO"), strKey, 100);
nTotalUserNum += CUserStatistics::GetInstance().GetGroupUserNum(nGroupIndex);
strUserNum.Format(_T("%d"), CUserStatistics::GetInstance().GetGroupUserNum(nGroupIndex));
m_ctrlUserStatList.SetItemText(nRow, nGroup + 1, strUserNum);
}
SetDlgItemInt(IDC_TOTALUSERNUM_EDIT, nTotalUserNum, TRUE);
}
void CChattingPage::OnBnClickedFlushStatlogBtn()
{
CMonitoringToolLog::GetInstance().FlushStatLog();
}
void CChattingPage::OnLbnDblclkChatmonitorList()
{
if (0 > m_ctrlChatMonitorList.GetCurSel())
{
MessageBox(GetMyINIString("LOCAL_STRING", "STRING_024"));
return;
}
unsigned long dwUID =
static_cast<unsigned long>(m_ctrlChatMonitorList.GetItemData(m_ctrlChatMonitorList.GetCurSel()));
if (0 == dwUID)
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_029"));
return;
}
char szBuffer[256];
m_ctrlChatMonitorList.GetText(m_ctrlChatMonitorList.GetCurSel(), szBuffer);
// 선택한 라인을 파싱하여 필요한 정보 추출
// ex) ServerName [Z:00][00:00][R:00] SenderName : Message (To: TargetName)
char* szServerName = strtok(szBuffer, " ");
strtok(NULL, "]");
strtok(NULL, "]");
char* szRace = strtok(NULL, "]");
char* szSenderName = strtok(NULL, " ");
TrimTab(szServerName, (int)strlen(szServerName)); // \t 정리
if (0 == strcmp(szServerName, "UNKNOWN"))
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_029"));
return;
}
if (0 == szSenderName)
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_029"));
return;
}
CWhisperDlg::WhisperDlgInfo stInfo;
ZeroMemory(&stInfo, sizeof(CWhisperDlg::WhisperDlgInfo));
stInfo.m_nDlgType = CWhisperDlg::WhisperDlgInfo::DLG_TYPE::WHISPER_TYPE_CLK;
stInfo.m_dwUID = dwUID;
stInfo.m_dwCID = m_CharacterID[dwUID];
stInfo.m_cRace = 0;
if(szRace[3] == 'H')
stInfo.m_cRace = 1;
else if(szRace[3] == 'A')
stInfo.m_cRace = 2;
strncpy(stInfo.m_szServerName, szServerName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
strncpy(stInfo.m_szCharName, szSenderName, CWhisperDlg::WhisperDlgInfo::MAX_NAME);
// 이미 창이 띄워져 있는지 체크
WhisperDlgMap::iterator find = m_WhisperDlgMap.find(dwUID);
if (find != m_WhisperDlgMap.end())
{
(find->second)->SetFocus();
return;
}
// 새 대화 모달리스 창 생성
m_lpWhisperDlg = new CWhisperDlg(this, stInfo);
m_lpWhisperDlg->Create(IDD_WHISPERDLG,this);
m_lpWhisperDlg->ShowWindow(SW_SHOW);
// 맵에 등록
m_WhisperDlgMap.insert(WhisperDlgMap::value_type(dwUID, m_lpWhisperDlg));
}
char* CChattingPage::TrimTab(char* szBuffer, int nSize)
{
char *temp = new char[nSize];
memset(temp, 0, nSize);
int j = 0;
for (int i=0; i < nSize; i++)
{
if (szBuffer[i] != '\t')
{
temp[j++] = szBuffer[i];
}
}
strcpy(szBuffer, temp);
delete temp;
return szBuffer;
}
void CChattingPage::OnBnClickedCallWhisperDlg()
{
if (false == theApp.IsAuthorized())
{
theApp.ReportResult(GetMyINIString("LOCAL_STRING", "STRING_044"));
return;
}
// 계정또는 UID로 대화 창을 띄울때는 별도의 ID를 임시키로 부여한다.
// Ack로 받는 ID로 창을 찾아 UID를 셋팅하고 사용.
// 이미 창이 띄워져 있는지 체크
WhisperDlgMap::iterator find = m_AccountDlgMap.find(m_dwAccountDlgID);
if (find != m_AccountDlgMap.end())
{
(find->second)->SetFocus();
return;
}
// 새로운 창을 생성하기 전에 ID 증가
++m_dwAccountDlgID;
CWhisperDlg::WhisperDlgInfo stInfo;
ZeroMemory(&stInfo, sizeof(CWhisperDlg::WhisperDlgInfo));
stInfo.m_nDlgType = CWhisperDlg::WhisperDlgInfo::DLG_TYPE::FINDUSER;
stInfo.m_dwUID = 0;
stInfo.m_dwDlgID = m_dwAccountDlgID;
m_lpWhisperDlg = new CWhisperDlg(this, stInfo);
m_lpWhisperDlg->Create(IDD_WHISPERDLG);
m_lpWhisperDlg->ShowWindow(SW_SHOW);
// 맵에 등록
m_AccountDlgMap.insert(WhisperDlgMap::value_type(m_dwAccountDlgID, m_lpWhisperDlg));
}
CWhisperDlg* CChattingPage::GetWhisperDlg(unsigned long dwUID)
{
WhisperDlgMap::iterator find = m_WhisperDlgMap.find(dwUID);
if (find != m_WhisperDlgMap.end())
{
return find->second;
}
else
{
return NULL;
}
}
CWhisperDlg* CChattingPage::GetAccountDlg(unsigned long dwDlgID)
{
WhisperDlgMap::iterator find = m_AccountDlgMap.find(dwDlgID);
if (find != m_AccountDlgMap.end())
{
return find->second;
}
else
{
return NULL;
}
}
BOOL CChattingPage::PreTranslateMessage(MSG* pMsg)
{
if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_RETURN))
{
if ((pMsg->hwnd == GetDlgItem(IDC_CHATMSG_EDIT)->m_hWnd))
{
OnBnClickedChatmsgSendBtn();
}
}
return CPropertyPage::PreTranslateMessage(pMsg);
}
void CChattingPage::SetLoginedNameEdit(const CString& strLoginedName)
{
m_strLoginedName = strLoginedName;
SetDlgItemText(IDC_LOGINEDNAME_EDIT, strLoginedName);
}
void CChattingPage::OnBnClickedGmloginedChk()
{
if (true == theApp.IsAuthorized())
{
unsigned char cSendType = 0;
if (BST_CHECKED != IsDlgButtonChecked(IDC_GMLOGINED_CHK))
{
cSendType = ChatToolPkt::ChatAdminStatus::LOGOUT;
}
else
{
cSendType = ChatToolPkt::ChatAdminStatus::LOGIN;
}
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[256];
for(int nIndex = 0; nIndex < (int)m_nMaxGroup; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
if (false == ClientNet::CChatServerEventHandler::SendAdminStatus(nServerGroup, 0, cSendType))
{
ERRLOG3(g_Log, "채팅 서버로 운영계정 로그인/아웃 패킷 전송 실패. 그룹: %d, GMName: %s, Type: %d",
nServerGroup, theApp.GetLoginedName(), cSendType);
}
}
}
}
void CChattingPage::OnBnClickedLangtypeChk()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
if (true == theApp.IsAuthorized())
{
if (BST_CHECKED != IsDlgButtonChecked(IDC_LANGTYPE_CHK))
{
m_usLocalLang = 0xFFFF;
}
else
{
m_usLocalLang = PRIMARYLANGID(GetSystemDefaultLangID());
}
}
}
BOOL CChattingPage::DestroyWindow()
{
CMonitoringToolSetup Setup = CMonitoringToolSetup::GetInstance();
char szKey[256];
for(int nIndex = 0; nIndex < (int)m_nMaxGroup; ++nIndex)
{
_snprintf(szKey, 256, "SERVER_GROUP_INDEX_%02d", nIndex);
unsigned int nServerGroup = Setup.GetInt("SERVER_GROUP_INFO", szKey);
if (false == ClientNet::CChatServerEventHandler::SendAdminStatus(
nServerGroup, 0, ChatToolPkt::ChatAdminStatus::LOGOUT))
{
ERRLOG2(g_Log, "채팅 서버로 운영계정 로그아웃 패킷 전송 실패. 그룹: %d, GMName: %s",
nServerGroup, theApp.GetLoginedName());
}
}
return CPropertyPage::DestroyWindow();
}
void CChattingPage::OnSize(UINT nType, int cx, int cy)
{
CPropertyPage::OnSize(nType, cx, cy);
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
CRect rect, rectc;
GetClientRect(rect);
if(m_ctrlChatMonitorList.GetSafeHwnd())
{
m_ctrlChatMonitorList.GetWindowRect(rectc);
m_ctrlChatMonitorList.MoveWindow(350, 35, rect.Width()-350, rectc.Height());
}
}