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>
912 lines
27 KiB
C++
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());
|
|
}
|
|
}
|