Files
Sun1602/Server/CommunityServer/PacketHandler/Handler_CW.Friend.cpp
T
2022-10-26 12:25:11 +08:00

766 lines
31 KiB
C++

#include "WorldServerPch.hxx"
#include "./Handler_CW.h"
#include <PacketStruct_WZ.h>
#include <ProhibitionWordParser.h>
//
#include "./PacketHandler.h"
#include "WorldServer.h"
//#include "Sessions/ServerSessionInWorld.h"
//#include "Channel/WorldChannelManager.h"
//#include "Channel/WorldChannel.h"
#include "Objects/WorldUserManager.h"
#include "Objects/WorldUser.h"
//#include "Services/ChattingService.h"
//#include "Services/Lotto/Lotto.h"
#include "Services/Group/GroupManager.h"
//#include "Services/Guild/WorldGuildManager.h"
#include "Services/Friends/FriendMap.h"
#include "Services/Friends/FriendInvitation.h"
//==================================================================================================
namespace ns_world { namespace handlers {
;
}}; //end of namespace
//==================================================================================================
//==================================================================================================
//==================================================================================================
#undef HANDLER_NODE_INFO
#define HANDLER_NODE_INFO(_category_, _protocol_, _phase_) \
void ns_world::handlers::Handler_CW::On##_protocol_(\
ns_world::ServerSessionInWorld* const server_session, \
const MSG_BASE* const msg_base, const uint16_t msg_size)
#define WAVERIX_WORLD_HANDLER_DEBUGGING() \
WAVERIX_WRAPPER((WAVERIX_LC_CALL4("waverix_log_trace_cw", \
__FUNCTION__, server_session, msg_base, msg_size)))
#if SUN_CODE_SAMPLE // to support visual assistx intelli-sense
ns_world::ServerSessionInWorld* server_session;
MSG_BASE* msg_base; uint16_t msg_size;
#endif
//==================================================================================================
//==================================================================================================
//==================================================================================================
// 친구 목록 요청
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_NEWLIST_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_NEWLIST_SYN* recv_msg = \
static_cast<const MSG_CW_FRIEND_NEWLIST_SYN*>(msg_base);
//
if (FlowControl::FCAssert(ns_world::FriendMap::PreparedFriendService(user)) == false)
{
SUNLOG(eCRITICAL_LOG, _T("|["__FUNCTION__"]|Msg=unexpected flow, ")
_T("user_guid=%u, char_name=%s|"), recv_msg->m_dwKey, user->GetCharName());
return;
};
MSG_CW_FRIEND_FRIENDLIST_ACK msg_friends;
MSG_CW_FRIEND_BLOCKLIST_ACK msg_blockchars;
MSG_CW_REVENGE_LIST_CMD msg_revenges;
ns_world::FriendMap* const friend_map = ns_world::FriendMap::Instance();
friend_map->LoadFriendList(user, msg_friends.sFriendStat, &msg_friends.byFriendStatNum);
friend_map->LoadBlockList(user, msg_blockchars.sBlockStat, &msg_blockchars.byBlockStatNum);
friend_map->LoadRevengeList(user, msg_revenges.sRevengeStat, &msg_revenges.byRevengeStatNum,
&msg_revenges.byRevengePoint);
user->SendPacket(&msg_friends, msg_friends.GetSize());
//_KR_0_20091021_FIRENDINVITATION_EXTEND //에이전트 서버에 친구추천 목록을 전달한다. (W->A->G)
if (ns_world::FriendInvitationInWorld* event = ns_world::FriendInvitationInWorld::Instance())
{
event->NotifyTotalFriendInvitationList(user, event->eMsgForward_ToClient);
};
user->SendPacket(&msg_blockchars, msg_blockchars.GetSize());
user->SendPacket(&msg_revenges, msg_revenges.GetSize());
SUNLOG(eFULL_LOG, _T("[%s][Guid:%u] Friend/Block/Revenge List Send"),
user->GetCharName(), user->GetUserGuid());
}
// 친구 요청
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_ADD_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_ADD_SYN* recv_msg = static_cast<const MSG_CW_FRIEND_ADD_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
if (ns_world::FriendMap::IsFriendTransaction(user)) {
return;
};
// NOTE: check whether own character addition request.
util::StrArrayForCharName finding_target_char_name;
_tcsncpy(finding_target_char_name, recv_msg->ptszCharNameTo,
_countof(finding_target_char_name));
finding_target_char_name[_countof(finding_target_char_name) - 1] = _T('\0');
if (_tcsnicmp(finding_target_char_name, user->GetCharName(),
_countof(finding_target_char_name)) == 0)
{
MSG_CW_FRIEND_ADD_NAK msg_nak;
msg_nak.m_byResult = msg_nak.FRIEND_IS_ME;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|Msg=disallow that own character add to friend list, ")
_T("char_name='%s'|"), finding_target_char_name);
return;
};
if (ns_world::FriendMap::FindFriendByCharName(user, finding_target_char_name) != NULL)
{
MSG_CW_FRIEND_ADD_NAK msg_nak;
msg_nak.m_byResult = msg_nak.ALREADY_FRIEND;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' already contains '%s' in friend list|"),
user->GetCharName(), finding_target_char_name);
return;
};
// game rules: 친구 최대 개수는 MAX_FRIEND_STAT_NUM 개 (90->200)
if (ns_world::FriendMap::GetNumberOfFriends(user) >= MAX_FRIEND_STAT_NUM)
{
MSG_CW_FRIEND_ADD_NAK msg_nak;
msg_nak.m_byResult = msg_nak.ERR_DEFAULT;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' can't add to friend list anymore|"),
user->GetCharName());
return;
};
// 일단 바~로 DB로 전송~
MSG_DW_FRIEND_ADD_SYN msg_syn;
msg_syn.m_CharGuidFrom = user->GetCharGuid();
_tcsncpy(msg_syn.m_ptszCharNameTo, finding_target_char_name,
_countof(msg_syn.m_ptszCharNameTo));
msg_syn.m_ptszCharNameTo[_countof(msg_syn.m_ptszCharNameTo) - 1] = _T('\0');
ns_world::ServerSessionInWorld* const dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy == NULL) {
// NOTE: f110906.4L, the world server will have been auto-closed
// when the database is disconnected... maybe...
return;
};
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
ns_world::FriendMap::StartFriendTransaction(user);
SUNLOG(eFULL_LOG, _T("Friend ADD to GameDBProxy(%s->%s)"),
user->GetCharName(), finding_target_char_name);
}
// 친구 삭제
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_DEL_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_DEL_SYN* recv_msg = static_cast<const MSG_CW_FRIEND_DEL_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
if (ns_world::FriendMap::IsFriendTransaction(user)) {
return;
};
util::StrArrayForCharName finding_target_char_name;
_tcsncpy(finding_target_char_name, recv_msg->ptszFriendName,
_countof(finding_target_char_name));
finding_target_char_name[_countof(finding_target_char_name) - 1] = _T('\0');
//
const STRUCT_FRIEND_INFO* friend_info = \
ns_world::FriendMap::FindFriendByCharName(user, finding_target_char_name);
if (friend_info == NULL)
{
MSG_CW_FRIEND_DEL_NAK msg_nak;
msg_nak.m_byResult = msg_nak.NOT_FRIEND_USER;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|Msg=can't find '%s' friend in friend list of '%s',CharGuid=%d|"),
finding_target_char_name, user->GetCharName(), user->GetCharGuid());
return;
};
MSG_DW_FRIEND_DEL_SYN msg_syn;
msg_syn.m_CharGuidFrom = user->GetCharGuid();
msg_syn.m_CharGuidTo = friend_info->dwFriendGuid;
// added data field to support _KR_0_20091021_FIRENDINVITATION_EXTEND //친구 삭제
msg_syn.m_Sts = ns_world::FriendInvitationInWorld::Instance()->GetFriendSts(\
user, friend_info->dwFriendGuid);
ns_world::ServerSessionInWorld* const dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy == NULL) {
// NOTE: f110906.4L, the world server will have been auto-closed
// when the database is disconnected... maybe...
return;
};
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
ns_world::FriendMap::StartFriendTransaction(user);
SUNLOG(eFULL_LOG, _T("Friend NO to GameDBProxy(%s->%s)"),
user->GetCharName(), finding_target_char_name);
}
// 차단 요청
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_BLOCK_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_BLOCK_SYN* recv_msg = static_cast<const MSG_CW_FRIEND_BLOCK_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
if (ns_world::FriendMap::IsFriendTransaction(user)) {
return;
};
// 그냥 차단하면 끝~
// NOTE: check whether own character addition request.
util::StrArrayForCharName finding_target_char_name;
_tcsncpy(finding_target_char_name, recv_msg->ptszBlockName,
_countof(finding_target_char_name));
finding_target_char_name[_countof(finding_target_char_name) - 1] = _T('\0');
if (_tcsnicmp(finding_target_char_name, user->GetCharName(),
_countof(finding_target_char_name)) == 0)
{
MSG_CW_FRIEND_BLOCK_NAK msg_nak;
msg_nak.m_byResult = msg_nak.BLOCKED_ME;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|Msg=disallow that own character delete from friend list, ")
_T("char_name='%s'|"), finding_target_char_name);
return;
};
const STRUCT_BLOCK_INFO* block_char_info = \
ns_world::FriendMap::FindBlockCharByCharName(user, finding_target_char_name);
if (block_char_info != NULL)
{
MSG_CW_FRIEND_BLOCK_NAK msg_nak;
msg_nak.m_byResult = msg_nak.ALREADY_BLOCKED;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eCRITICAL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' is already blocked in friend list of ''%s'|"),
finding_target_char_name, user->GetCharName());
return;
};
// game rules: 블록 최대 개수는 MAX_BLOCK_STAT_NUM 개 (90->200)
if (ns_world::FriendMap::GetNumberOfBlocks(user) >= MAX_BLOCK_STAT_NUM)
{
MSG_CW_FRIEND_BLOCK_NAK msg_nak;
msg_nak.m_byResult = msg_nak.ERR_DEFAULT;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' can't add from blocking list anymore|"),
user->GetCharName());
return;
};
MSG_DW_FRIEND_BLOCK_SYN msg_syn;
msg_syn.m_CharGuidFrom = user->GetCharGuid();
_tcsncpy(msg_syn.m_ptszCharNameTo, finding_target_char_name,
_countof(msg_syn.m_ptszCharNameTo));
msg_syn.m_ptszCharNameTo[_countof(msg_syn.m_ptszCharNameTo) - 1] = _T('\0');
ns_world::ServerSessionInWorld* const dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy == NULL) {
// NOTE: f110906.4L, the world server will have been auto-closed
// when the database is disconnected... maybe...
return;
};
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
ns_world::FriendMap::StartFriendTransaction(user);
SUNLOG(eFULL_LOG, _T("Friend Block to GameDBProxy(%s->%s)"),
user->GetCharName(), finding_target_char_name);
}
// 차단 삭제 요청
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_BLOCK_FREE_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_BLOCK_FREE_SYN* recv_msg = \
static_cast<const MSG_CW_FRIEND_BLOCK_FREE_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
if (ns_world::FriendMap::IsFriendTransaction(user)) {
return;
};
// NOTE: check whether own character addition request.
util::StrArrayForCharName finding_target_char_name;
_tcsncpy(finding_target_char_name, recv_msg->ptszBlockName,
_countof(finding_target_char_name));
finding_target_char_name[_countof(finding_target_char_name) - 1] = _T('\0');
const STRUCT_BLOCK_INFO* block_char_info = \
ns_world::FriendMap::FindBlockCharByCharName(user, finding_target_char_name);
if (block_char_info == NULL)
{
MSG_CW_FRIEND_BLOCK_FREE_NAK msg_nak;
msg_nak.m_byResult = msg_nak.NOT_BLOCKED;
user->SendPacket(&msg_nak, sizeof(msg_nak));
return;
};
// 정확한 차단 정보가 있으면 차단 해제 요청을 DB에 보낸다
MSG_DW_FRIEND_BLOCK_FREE_SYN msg_syn;
msg_syn.m_CharGuidFrom = user->GetCharGuid();
msg_syn.m_CharGuidTo = block_char_info->dwBlockGuid;
ns_world::ServerSessionInWorld* const dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy == NULL) {
// NOTE: f110906.4L, the world server will have been auto-closed
// when the database is disconnected... maybe...
return;
};
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
ns_world::FriendMap::StartFriendTransaction(user);
SUNLOG(eFULL_LOG, _T("Friend Block Free to GameDBProxy(%s->%s)"),
user->GetCharName(), finding_target_char_name);
}
// 친구 채팅
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_CHAT_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_CHAT_SYN* recv_msg = static_cast<const MSG_CW_FRIEND_CHAT_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
util::StrArrayForGenericChattingMsg chatting_msg;
BOOST_STATIC_ASSERT(_countof(chatting_msg) == _countof(recv_msg->ptszChatMsg));
const size_t chat_msg_length = min(_countof(recv_msg->ptszChatMsg) - 1, recv_msg->byMsgLength);
if (chat_msg_length == 0 ||
chat_msg_length != recv_msg->byMsgLength ||
recv_msg->GetSize() != msg_size)
{
return;
};
//
MSG_CW_FRIEND_CHAT_NAK msg_nak;
BOOST_STATIC_ASSERT(_countof(msg_nak.ptszFriendNameTo) == _countof(recv_msg->ptszFriendNameTo));
strncpy(msg_nak.ptszFriendNameTo, recv_msg->ptszFriendNameTo,
_countof(msg_nak.ptszFriendNameTo));
msg_nak.ptszFriendNameTo[_countof(msg_nak.ptszFriendNameTo) - 1] = '\0';
// 모든 채팅에서 크기가 0이거나 실제 내용이 없으면 무시
// if (!recv_msg->byMsgLength || !_tcslen(recv_msg->ptszChatMsg))
// {
// SUNLOG(eFULL_LOG, "채팅 내용 없음");
// return;
// }
ns_world::GroupManager* const group_manager = ns_world::GroupManager::Instance();
ns_world::WorldUser* const friend_user = \
ns_world::WorldUserManager::Instance()->FindUserByCharName(msg_nak.ptszFriendNameTo);
//__KR_001355_20090608_GROUPINGSYSTEM_CW
const STRUCT_GROUP_MEMBER_INFO* group_member_info = (friend_user == NULL) ?
NULL : group_manager->FindGroupMember(user, friend_user->GetCharGuid());
// Check online
const bool not_entered_state = \
(friend_user == NULL || friend_user->GetConnectedCharInfo().zone_type == eZONETYPE_LOBBY);
if (not_entered_state && group_member_info == NULL)
{
msg_nak.m_byResult = msg_nak.OFFLINE_FRIEND;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' does not enable service, reason=offline|"),
msg_nak.ptszFriendNameTo);
return;
};
const STRUCT_FRIEND_INFO* friend_info = \
ns_world::FriendMap::FindFriend(user, friend_user->GetCharGuid());
if (friend_info == NULL && group_member_info == NULL)
{
if (ns_world::FriendMap::FindFriend(friend_user, user->GetCharGuid()) == NULL)
{ // 상대에게도 친구 아이다!!
msg_nak.m_byResult = msg_nak.NOT_FRIEND;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' is not friend with requester ('%s')|"),
msg_nak.ptszFriendNameTo, user->GetCharName());
return;
};
};
const bool enabled_chatting = \
(friend_user->GetChattingMode().friend_chatting_blocked == false) &&
(ns_world::FriendMap::FindBlockChar(friend_user, user->GetCharGuid()) == NULL);
if (enabled_chatting == false && group_member_info == NULL)
{
msg_nak.m_byResult = msg_nak.BLOCK_CHAT;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' can not communicate, reason=chatting blocked|"),
msg_nak.ptszFriendNameTo);
return;
};
// rebuild chatting message, chat_msg_length does not contain null character
assert(chat_msg_length < _countof(chatting_msg)); // already calculated
strncpy(chatting_msg, recv_msg->ptszChatMsg, chat_msg_length);
chatting_msg[chat_msg_length] = '\0';
chatting_msg[_countof(chatting_msg) - 1] = '\0';
//
if (ProhibitionWordParser::Instance()->CheckFilter(chatting_msg) == false)
{
MSG_CW_CHAT_NORMAL_NAK chat_msg_nak;
chat_msg_nak.m_wErrorCode = RC::RC_CHAT_USE_BAN_WORD;
user->SendPacket(&chat_msg_nak, sizeof(chat_msg_nak));
SUNLOG(eFULL_LOG,
_T("|["__FUNCTION__"]|Msg='%s' use banned words|"),
user->GetCharName());
return;
};
//
MSG_CW_FRIEND_CHAT_BRD msg_brd;
strncpy(msg_brd.ptszFriendNameFrom, user->GetCharName(), _countof(msg_brd.ptszFriendNameFrom));
msg_brd.ptszFriendNameFrom[_countof(msg_brd.ptszFriendNameFrom) - 1] = '\0';
//
BOOST_STATIC_ASSERT(_countof(msg_brd.ptszChatMsg) == _countof(chatting_msg));
msg_brd.byMsgLength = static_cast<uint8_t>(::strlen(chatting_msg));
strncpy(msg_brd.ptszChatMsg, chatting_msg, _countof(msg_brd.ptszChatMsg));
//
friend_user->SendPacket(&msg_brd, msg_brd.GetSize());
//
GAMELOG->WriteFriendChat(user, server_session->GetChannelID(),
friend_user, chatting_msg, _countof(chatting_msg) - 1);
SUNLOG(eFULL_LOG, _T("Friend Chat[%s -> %s]: %s"),
user->GetCharName(), friend_user->GetCharName(), chatting_msg);
}
// 1:1 대화 거부 체크
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_CHATBLOCK_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_CHATBLOCK_SYN* recv_msg = \
static_cast<const MSG_CW_FRIEND_CHATBLOCK_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
// 해당 유저의 1:1대화를 거부한다
ns_world::ChattingMode chatting_mode = user->GetChattingMode();
;{ // 이 유저의 귓말 켬/끔 상태 세팅
chatting_mode.friend_chatting_blocked = (recv_msg->m_bBlock != false);
ns_world::WorldUserManager* const user_manager = ns_world::WorldUserManager::Instance();
user_manager->ChangeChattingMode(user, chatting_mode);
};
MSG_CW_FRIEND_CHATBLOCK_ACK msg_ack;
msg_ack.m_bNowBlock = chatting_mode.friend_chatting_blocked;
user->SendPacket(&msg_ack, sizeof(msg_ack));
SUNLOG(eFULL_LOG, _T("[%s] Friend Chat Block(%u)"),
user->GetCharName(), chatting_mode.friend_chatting_blocked);
}
// 친구/리벤지/길드원/그룹원 상세정보 요청
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_STATUS_REQ, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_STATUS_REQ* recv_msg = \
static_cast<const MSG_CW_FRIEND_STATUS_REQ*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
ns_world::ServerSessionInWorld* const dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy == NULL) {
// NOTE: f110906.4L, the world server will have been auto-closed
// when the database is disconnected... maybe...
return;
};
// NOTE: updates logic by the _NA_0_20100527_ADD_CHAR_RELATION_MEMO contents
RC::eFRIEND_RESULT friend_result = \
ns_world::FriendMap::CheckAccessibleFriendInfo(user, recv_msg->m_dwToCharGuid);
const ns_world::ConnectedCharInfo& char_info = user->GetConnectedCharInfo();
if (friend_result == RC::RC_FRIEND_SUCCESS)
{
MSG_DW_FRIEND_DETAIL_INFO_SYN msg_syn;
msg_syn.m_dwKey = char_info.char_guid;
msg_syn.m_dwToCharGuid = recv_msg->m_dwToCharGuid;
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
}
else if (friend_result == RC::RC_FRIEND_NOTGUILDMEMBER)
{
MSG_WZ_GUILD_CHECK_CONDITION_ACCESS_DETAIL_INFO_SYN msg_syn;
msg_syn.m_dwKey = char_info.char_guid;
msg_syn.m_guildGuid = char_info.guild_guid;
msg_syn.m_dwToCharGuid = recv_msg->m_dwToCharGuid;
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
}
else
{
MSG_CW_FRIEND_STATUS_NAK nak_msg;
nak_msg.m_byErrorCode = static_cast<uint8_t>(friend_result);
user->SendPacket(&nak_msg, sizeof(nak_msg));
};
}
//_NA_0_20100527_ADD_CHAR_RELATION_MEMO
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_MEMO_UPDATE_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_MEMO_UPDATE_SYN* recv_msg = \
static_cast<const MSG_CW_FRIEND_MEMO_UPDATE_SYN*>(msg_base);
if (FlowControl::FCAssert(sizeof(*recv_msg) == msg_size) == false) {
return;
};
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
RC::eFRIEND_RESULT friend_result = \
ns_world::FriendMap::CheckAccessibleFriendInfo(user, recv_msg->m_dwToCharGuid);
switch (friend_result)
{
case RC::RC_FRIEND_SUCCESS:
case RC::RC_FRIEND_NOTGUILDMEMBER: // 한번 이상 접속 하지 않은 오프라인 길드원
{ // 여기까지 왔다면, 상세 정보 창을 열었다는 뜻이며, 길드서버에 선 체크를 한 상황이므로 통과 한다.
MSG_DW_FRIEND_MEMO_UPDATE_SYN msg_syn;
BOOST_STATIC_ASSERT(_countof(msg_syn.m_ptszMemo) == _countof(recv_msg->m_ptszMemo));
//
msg_syn.m_dwKey = user->GetCharGuid();
msg_syn.m_dwToCharGuid = recv_msg->m_dwToCharGuid;
_tcsncpy(msg_syn.m_ptszMemo, recv_msg->m_ptszMemo, _countof(msg_syn.m_ptszMemo));
msg_syn.m_ptszMemo[_countof(msg_syn.m_ptszMemo) - 1] = _T('\0');
ns_world::ServerSessionInWorld* dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy != NULL) {
dbproxy->SendPacket(&msg_syn, sizeof(msg_syn));
}
else {
friend_result = RC::RC_FRIEND_FAIL;
};
}
break;
};
if (friend_result != RC::RC_FRIEND_SUCCESS)
{
MSG_CW_FRIEND_MEMO_UPDATE_NAK nak_msg;
nak_msg.m_byErrorCode = static_cast<uint8_t>(friend_result);
user->SendPacket(&nak_msg, sizeof(nak_msg));
};
}
// 친구 따라가기
HANDLER_NODE_INFO(CW_FRIEND, CW_FRIEND_STATUS_JOIN_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_FRIEND_STATUS_JOIN_SYN* recv_msg = \
static_cast<const MSG_CW_FRIEND_STATUS_JOIN_SYN*>(msg_base);
//
MSG_CW_FRIEND_STATUS_JOIN_NAK msg_nak;
;{
ZeroMemory(&msg_nak, sizeof(msg_nak));
new (&msg_nak) MSG_CW_FRIEND_STATUS_JOIN_NAK;
};
strncpy(msg_nak.m_ptszCharName, recv_msg->m_ptszCharName, _countof(msg_nak.m_ptszCharName));
msg_nak.m_ptszCharName[_countof(msg_nak.m_ptszCharName) - 1] = '\0';
ns_world::WorldUser* const target_user = \
ns_world::WorldUserManager::Instance()->FindUserByCharName(msg_nak.m_ptszCharName);
if (target_user == NULL)
{ // not found, not connected, etc...
msg_nak.m_byErrorCode = RC::RC_FRIEND_NOTCONNECTED; // 해당 유저 미접속
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG, _T("|["__FUNCTION__"]|Msg=target('%s') is not connecting|"),
msg_nak.m_ptszCharName);
return;
};
const ns_world::ConnectedCharInfo& target_char_info = target_user->GetConnectedCharInfo();
// __KR_001355_20090608_GROUPINGSYSTEM_CW
const STRUCT_GROUP_MEMBER_INFO* group_member_info = \
ns_world::GroupManager::Instance()->FindGroupMember(user, target_char_info.char_guid);
// History
// BUG:5045 문상현, remove the check condition whether group_member_info is null
if (user->GetUserAccountInfo().channel != target_user->GetUserAccountInfo().channel)
{
msg_nak.m_byErrorCode = RC::RC_FRIEND_DIFFCHANNEL; // 채널 달라요~
user->SendPacket(&msg_nak, sizeof(msg_nak));
int target_channel = target_user->GetUserAccountInfo().channel ?
target_user->GetUserAccountInfo().channel->GetChannelID() : 0;
SUNLOG(eFULL_LOG, _T("|["__FUNCTION__"]|Msg=target('%s') is located on other channel(%d), ")
_T("current channel(%d)|"),
msg_nak.m_ptszCharName, target_channel,
user->GetUserAccountInfo().channel->GetChannelID());
return;
};
//
const STRUCT_FRIEND_INFO* friend_info = \
ns_world::FriendMap::FindFriend(user, target_char_info.char_guid);
if ((friend_info == NULL || friend_info->dwFriendGuid != target_char_info.char_guid) &&
(group_member_info == NULL))
{
// check whether the revenging target
const STRUCT_REVENGE_INFO* revenge_info = \
ns_world::FriendMap::FindRevengeChar(user, target_char_info.char_guid);
if (revenge_info == NULL ||
revenge_info->dwRevengeCharGuid != target_char_info.char_guid)
{
msg_nak.m_byErrorCode = RC::RC_FRIEND_NOTFRIEND; // 친구가 아니거나 잘못된 정보임
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG, _T("|["__FUNCTION__"]|Msg=target('%s')'s revenge info. is invalid|"),
msg_nak.m_ptszCharName);
return;
};
};
// 방 타입이 잘못되었으면
if (target_char_info.zone_type != eZONETYPE_LOBBY &&
target_char_info.zone_type != eZONETYPE_CHUNTING)
{
msg_nak.m_byErrorCode = RC::RC_FRIEND_INVALIDZONE;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eFULL_LOG, _T("|["__FUNCTION__"]|Msg=target('%s')'s is located on invalid zone(%d)"),
msg_nak.m_ptszCharName, target_char_info.zone_type);
return;
};
// 현재 배틀존 정보 넣는다
MSG_CW_FRIEND_STATUS_JOIN_ACK msg_ack;
msg_ack.m_byZoneType = target_char_info.zone_type;
msg_ack.m_dwZoneKey = target_char_info.zone_key;
BOOST_STATIC_ASSERT(_countof(msg_ack.m_ptszCharName) == _countof(msg_nak.m_ptszCharName));
strncpy(msg_ack.m_ptszCharName, msg_nak.m_ptszCharName, _countof(msg_ack.m_ptszCharName));
user->SendPacket(&msg_ack, sizeof(msg_ack));
SUNLOG(eFULL_LOG, _T("CW_FRIEND_STATUS_JOIN_ACK send[requester char:%u]")
_T("[Target:%s][ZT:%u][ZK:%u]"),
user->GetCharGuid(),
msg_ack.m_ptszCharName,
target_char_info.zone_type,
target_char_info.zone_key);
}
// 리벤지 리스트에서 삭제
HANDLER_NODE_INFO(CW_REVENGE, CW_REVENGE_DEL_SYN, PHASE_SERVICE)
{
__TOUCHED((server_session, msg_base, msg_size));WAVERIX_WORLD_HANDLER_DEBUGGING();
ns_world::WorldUser* const user = FIND_USER_FROM_AGENT_MSG(msg_base);
if (user == NULL) {
return;
};
const MSG_CW_REVENGE_DEL_SYN* recv_msg = static_cast<const MSG_CW_REVENGE_DEL_SYN*>(msg_base);
//
if (CheckEnabledChattingState(user, server_session) == false) {
return;
};
if (ns_world::FriendMap::IsFriendTransaction(user)) {
return;
};
// 혹시 있을지 모르는 문자열 길이 오류 보정
// NOTE: fixed, prevent changes about cg network buffer stream
util::StrArrayForCharName char_name;
strncpy(char_name, recv_msg->m_ptszCharName, _countof(char_name));
char_name[_countof(char_name) - 1] = '\0';
ns_world::ServerSessionInWorld* const dbproxy = \
ns_world::WorldServer::Instance()->GetGameDBProxy();
if (dbproxy == NULL) {
return;
};
// 나쁜친구 맞아?
const STRUCT_REVENGE_INFO* revenge_info = \
ns_world::FriendMap::FindRevengeCharByCharName(user, char_name);
if (revenge_info == NULL)
{
MSG_CW_REVENGE_DEL_NAK msg_nak;
CopyMemory(msg_nak.m_ptszCharName, char_name, sizeof(msg_nak.m_ptszCharName));
msg_nak.m_byErrorCode = RC::RC_REVENGE_INVALID_CHAR;
user->SendPacket(&msg_nak, sizeof(msg_nak));
SUNLOG(eCRITICAL_LOG, _T("Revenge Del Error - Not Revenge[%s][CharGuid:%u]->[%s]"),
user->GetCharName(), user->GetCharGuid(), char_name);
return;
};
const ns_world::ConnectedCharInfo& char_info = user->GetConnectedCharInfo();
MSG_DW_CHAO_REMOVE_REVENGE_CHAR_SYN msg_dg_syn;
msg_dg_syn.m_dwKey = server_session->GetChannelID(); // ... m_dwKey usage warnings
msg_dg_syn.m_CharGuidFrom = char_info.char_guid;
msg_dg_syn.m_RevengeGuidTo = revenge_info->dwRevengeCharGuid;
//
dbproxy->SendPacket(&msg_dg_syn, sizeof(msg_dg_syn));
ns_world::FriendMap::StartFriendTransaction(user);
SUNLOG(eFULL_LOG, _T("Revenge Del to GameDBProxy(%s->%s)"),
char_info.char_name, revenge_info->sPacketInfo.ptszRevengeName);
}