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>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,910 @@
#include "stdafx.h"
#include "AdminToolDispatch.h"
#include <Log/ServerLog.h>
#include <Network/Address/INET_Addr.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Packet/PacketStruct/CharAdminPacket.h>
#include <Network/Packet/PacketStruct/GameEventPacket.h>
#include <Network/Packet/PacketStruct/CharLoginOutPacketStruct.h>
#include <Network/SendPacket/SendAdminTool.h>
#include <Network/SendPacket/SendServerInfo.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Network/Dispatch/GameClient/SendCharAdmin.h>
#include <DataStorage/AdminDataMgr.h>
#include <DataStorage/SessionData.h>
#include <DataStorage/SessionDataMgr.h>
#include <DataStorage/StoreData.h>
#include <DataStorage/StoreDataMgr.h>
#include <DataStorage/CharacterData.h>
#include <DataStorage/CharacterDataMgr.h>
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <DB/GuildDBComponent.h>
#include <GameEvent/GameEventDBMgr.h>
#include <Utility/Setup/ServerSetup.h>
#include <Creature/Character/CharacterClass.h>
#include <Network/Packet/PacketStruct/GuildPacket.h>
#include <Community/Guild/GuildDB.h>
#include <Community/Guild/GuildDBMgr.h>
namespace DBAgent
{
// forward decl.
bool GetUIDCIDFromName(const char* szName, unsigned long& dwUID_Out,
unsigned long& dwCID_Out, unsigned char& cOldServerGroupID);
CMultiDispatch& CAdminToolDispatch::GetDispatchTable()
{
static CMultiDispatch gameDispatch;
return gameDispatch;
}
CAdminToolDispatch::CAdminToolDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE),
m_dwServerID(0)
{
}
CAdminToolDispatch::~CAdminToolDispatch()
{
}
void CAdminToolDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/AdminToolServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
}
void CAdminToolDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/AdminToolServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
if(0 != m_dwServerID)
{
GetDispatchTable().RemoveDispatch(m_dwServerID);
if(0LL != m_AdminItemSerialMgr.GetItemSerial())
{
// 아이템 시리얼 DB에 저장
m_AdminItemSerialMgr.SaveItemSerial(
CDBSingleObject::GetInstance(), m_dwServerID);
}
}
}
bool CAdminToolDispatch::DispatchPacket(PktBase* lpPktBase)
{
bool bResult = false;
PktBase::CMDType cCmd = lpPktBase->GetCmd();
switch(cCmd)
{
case CmdSysServerLogin: bResult = ParseServerLogin(static_cast<PktSL*>(lpPktBase)); break;
case CmdSysServerLogout: bResult = ParseServerLogout(lpPktBase); break;
case CmdUserKill: bResult = ParseUserKill(static_cast<PktUK*>(lpPktBase)); break;
case CmdAdminToolGetData: bResult = ParseGetData(static_cast<PktAdminToolGetData*>(lpPktBase)); break;
case CmdAdminToolSetData: bResult = ParseSetData(static_cast<PktAdminToolSetData*>(lpPktBase)); break;
case CmdItemQtyCheck: bResult = ParseItemQtyCheck(static_cast<PktItemQtyControl*>(lpPktBase)); break;
case CmdGuildPosition: bResult = ParseGuildPosition(static_cast<PktGuildPosition*>(lpPktBase)); break;
default:
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ 운영툴 서버 패킷 처리 실패 : 없는 커맨드입니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
bResult = true;
break;
}
if(!bResult)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ 운영툴 서버 패킷 처리 실패 : 처리를 실패했습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
}
return true;
}
bool CAdminToolDispatch::ParseServerLogin(PktSL* lpPktSL)
{
m_dwServerID = lpPktSL->m_dwServerID;
INFLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 운영툴 서버 연결 시도 : 패킷 받음",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
GET_MULTI_DISPATCH(lpAdminToolDispatch, m_dwServerID,
CAdminToolDispatch, GetDispatchTable());
if(0 != lpAdminToolDispatch)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 운영툴 서버 연결 실패 : 이미 연결이 있습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
}
else
{
// Dispatch 세팅.
GetDispatchTable().SetDispatch(m_dwServerID, this);
// 아이템 시리얼 로드.
if(!m_AdminItemSerialMgr.LoadItemSerial(CDBSingleObject::GetInstance(), m_dwServerID))
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 운영툴 서버 연결 실패 : 아이템 시리얼 로드 실패. 접속을 끊습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
return false;
}
return SendPacket::ServerLoginAck(m_SendStream,
m_dwServerID, m_AdminItemSerialMgr.GetItemSerial());
}
return true;
}
bool CAdminToolDispatch::ParseServerLogout(PktBase* lpPktBase)
{
// 받은 패킷 그대로 돌려 준다.
char* lpBuffer = m_SendStream.GetBuffer(sizeof(PktBase));
if(0 != lpBuffer)
{
return m_SendStream.WrapHeader(sizeof(PktBase), CmdSysServerLogout, 0, 0);
}
return false;
}
bool CAdminToolDispatch::ParseUserKill(PktUK* lpPktUK)
{
using namespace DataStorage;
// 접속 DB를 전부 뒤져서, 계정과 IP가 일치하는 넘한테 뜨거운 맛을 보여 준다.
CSessionData* lpSessionData =
CSessionDataMgr::GetInstance().GetOpenSession(lpPktUK->m_dwUserID);
if(0 == lpSessionData)
{
ERRLOG1(g_Log, "UID:%10u / 운영툴 서버 유저 접속 끊기 실패 : 유저가 없습니다", lpPktUK->m_dwUserID);
}
else
{
SERVER_ID serverID;
serverID.dwID = lpSessionData->GetServerID();
CSessionData::SessionState eSessionState = lpSessionData->GetSessionState();
if ((serverID.GetType() == CServerSetup::AuthServer && CSessionData::SE_USER_ENABLED != eSessionState) ||
(serverID.GetType() == CServerSetup::GameServer && CSessionData::SE_CHAR_ENABLED != eSessionState))
{
ERRLOG3(g_Log, "UID:%10u / ServerID:0x%08X / ST:%s / 운영툴 서버 유저 접속 끊기 실패 : 유저나 캐릭터가 비활성화되어 있습니다",
lpPktUK->m_dwUserID, serverID.dwID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
else if(!SendPacket::UserKill(*lpSessionData))
{
ERRLOG3(g_Log, "UID:%10u / ServerID:0x%08X / ST:%s / 운영툴 서버 유저 접속 끊기 실패 : 접속 끊기 패킷 보내기 실패",
lpPktUK->m_dwUserID, serverID.dwID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
}
return true;
}
bool CAdminToolDispatch::ParseGetData(PktBase* lpPktBase)
{
// 데이터 얻어 오기. 패킷 오면 캐릭터 정보 및 창고 정보를 준다.
PktAdminToolGetData* lpPktAdminToolGetData = static_cast<PktAdminToolGetData*>(lpPktBase);
switch(lpPktAdminToolGetData->m_cType)
{
case PktAdminToolGetData::GET_CHAR_DATA:
return ParseAdminToolGetData(lpPktAdminToolGetData);
case PktAdminToolGetData::CHANGE_CHAR_NAME:
return ParseAdminToolChangeName(lpPktAdminToolGetData);
default:
ERRLOG2(g_Log, "IP:%15s / Cmd:%d / 알 수 없는 운영툴 데이터 얻기 커맨드입니다.",
GetRemoteAddr().get_addr_string(), lpPktAdminToolGetData->m_cType);
return true;
}
return false;
}
bool CAdminToolDispatch::ParseSetData(PktBase* lpPktBase)
{
// 데이터 기록하기. 패킷 오면 캐릭터 관련 데이터를 쓴다.
// CharLogin때 보내주는 데이터, 창고 데이터 1, 창고 데이터 2, 창고 정보
// 데이터 얻어 오기. 패킷 오면 캐릭터 정보 및 창고 정보를 준다.
PktAdminToolSetData* lpPktAdminToolSetData = static_cast<PktAdminToolSetData*>(lpPktBase);
switch(lpPktAdminToolSetData->m_cType)
{
case PktAdminToolSetData::CHAR_BASIC_DATA:
case PktAdminToolSetData::CHAR_EXTRA_DATA:
case PktAdminToolSetData::CHAR_FRIEND_DATA:
case PktAdminToolSetData::CHAR_BAN_DATA:
case PktAdminToolSetData::STORE_12_DATA:
case PktAdminToolSetData::STORE_34_DATA:
case PktAdminToolSetData::OPEN_UPDATE_DATA:
case PktAdminToolSetData::FINISH_UPDATE_DATA:
return ParseAdminToolSetData(lpPktAdminToolSetData);
case PktAdminToolSetData::RELOAD_ADMINLIST:
return DataStorage::CAdminDataMgr::GetInstance().LoadAdminList(CDBSingleObject::GetInstance());
default:
ERRLOG2(g_Log, "IP:%15s / Cmd:%d / 알 수 없는 운영자 데이터 셋 패킷 커맨드입니다",
GetRemoteAddr().get_addr_string(), lpPktAdminToolSetData->m_cType);
return true;
}
return false;
}
bool CAdminToolDispatch::ParseAdminToolGetData(PktAdminToolGetData* lpPktAdminToolGetData)
{
// DBRequestKey.
unsigned long dwRequestKey = lpPktAdminToolGetData->m_dwRequestKey;
unsigned long dwUID = lpPktAdminToolGetData->m_dwUID;
unsigned long dwCID = lpPktAdminToolGetData->m_dwCID;
unsigned char cOldServerGroupID = 0;
if (UnifiedConst::Part2Selectable == CServerSetup::GetInstance().GetAgentServerType())
{
cOldServerGroupID = lpPktAdminToolGetData->m_cOldServerGroupID;
}
else
{
cOldServerGroupID = static_cast<unsigned char>(
CServerSetup::GetInstance().GetAgentServerType());
}
PktAdminToolGetData::GetDataType eDataType =
static_cast<PktAdminToolGetData::GetDataType>(lpPktAdminToolGetData->m_cType);
unsigned short wError = 0;
if(eDataType != PktAdminToolGetData::GET_CHAR_DATA)
{
// 잘못된 패킷임
wError = PktAdminToolGetData::INVALID_REQUEST;
}
else
{
// UID, CID가 없으면 캐릭터 이름을 가지고 UID와 CID를 얻어 온다.
if(0 == dwUID || 0 == dwCID || 0 == cOldServerGroupID)
{
if(!GetUIDCIDFromName(lpPktAdminToolGetData->m_szName,
dwUID, dwCID, cOldServerGroupID))
{
// DB Query 실패.
wError = PktAdminToolGetData::GET_UIDCID_QUERY_FAILED;
}
if(0 == dwUID || 0 == dwCID || 0 == cOldServerGroupID)
{
// 얻어온 데이터가 이상함.
wError = PktAdminToolGetData::INVALID_UID_CID_DATA;
}
}
DETLOG4(g_Log, "UID:%10u / ServerGroupID:%d / CID:%10u / IP:%15s / 운영툴로부터 데이터 요청 받음",
dwUID, cOldServerGroupID, dwCID, GetRemoteAddr().get_addr_string());
if(0 == wError)
{
using namespace DataStorage;
CStoreData* lpStoreData = 0;
CCharacterData* lpCharacterData = 0;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(dwUID);
if(0 != lpSessionData)
{
// 이미 로드된 세션에서 데이터 가져옴.
if(dwUID == lpSessionData->GetUID())
{
lpStoreData = lpSessionData->GetStoreData();
}
if(dwCID == lpSessionData->GetCID())
{
lpCharacterData = lpSessionData->GetCharacterData();
}
}
// 캐쉬에서 데이터 로드. 캐쉬에 데이터가 없으면, DB에서 로드해서 캐쉬에 추가.
if(0 == lpStoreData)
{
lpStoreData = CStoreDataMgr::GetInstance().GetLogoutData(
UnifiedStoreKey(dwUID, cOldServerGroupID));
}
if(0 == lpCharacterData)
{
lpCharacterData = CCharacterDataMgr::GetInstance().GetLogoutData(dwCID);
}
if(0 == lpStoreData)
{
wError = PktAdminToolGetData::GET_STORE_QUERY_FAILED;
}
else if(0 == lpCharacterData)
{
wError = PktAdminToolGetData::GET_CHAR_DATA_QUERY_FAILED;
}
else
{
SendPacket::TotalDataToAdminTool(GetSendStream(), dwRequestKey,
GetRemoteAddr().get_addr_in().sin_addr, *lpStoreData, *lpCharacterData);
}
}
}
// 최종 전송
return SendPacket::AdminToolGetDataAck(GetSendStream(),
PktAdminToolGetData::FINISH_GET_DATA, dwRequestKey, dwUID, dwCID, 0, 0, wError, cOldServerGroupID);
}
bool CAdminToolDispatch::ParseAdminToolSetData(PktAdminToolSetData* lpPktAdminToolSetData)
{
SERVER_ID serverID;
serverID.dwID = m_dwServerID;
unsigned long dwUID = lpPktAdminToolSetData->m_dwUID;
unsigned long dwCID = lpPktAdminToolSetData->m_dwCID;
unsigned long dwRequestKey = lpPktAdminToolSetData->m_dwRequestKey;
unsigned long dwDataSize = lpPktAdminToolSetData->GetLen() - sizeof(PktAdminToolSetData);
unsigned char cType = lpPktAdminToolSetData->m_cType;
unsigned char cOldServerGroupID = 0;
if (UnifiedConst::Part2Selectable == CServerSetup::GetInstance().GetAgentServerType())
{
cOldServerGroupID = lpPktAdminToolSetData->m_cOldServerGroupID;
}
else
{
cOldServerGroupID = static_cast<unsigned char>(
CServerSetup::GetInstance().GetAgentServerType());
}
unsigned short wError = 0;
if(0 == dwUID || 0 == dwCID)
{
wError = PktAdminToolSetData::INVALID_UID_CID_ERROR;
}
else
{
DETLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영자가 운영툴로 데이터 세팅 시도",
dwUID, dwCID, GetRemoteAddr().get_addr_string());
using namespace DataStorage;
CStoreData* lpStoreData = 0;
CCharacterData* lpCharacterData = 0;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(dwUID);
if(0 != lpSessionData)
{
if(CSessionData::SE_USER_ENABLED == lpSessionData->GetSessionState() ||
CSessionData::SE_CHAR_ENABLED == lpSessionData->GetSessionState())
{
// 활성화된 캐릭터 편집 에러
wError = PktAdminToolSetData::LOGIN_ANOTHER_GAMESERVER;
}
else
{
// 이미 로드된 세션에서 데이터 가져옴.
if(dwUID == lpSessionData->GetUID())
{
lpStoreData = lpSessionData->GetStoreData();
}
if(dwCID == lpSessionData->GetCID())
{
lpCharacterData = lpSessionData->GetCharacterData();
}
}
}
if(0 == wError)
{
// 캐쉬에서 데이터 로드. 캐쉬에 데이터가 없으면, DB에서 로드해서 캐쉬에 추가.
if(0 == lpStoreData)
{
lpStoreData = CStoreDataMgr::GetInstance().GetLogoutData(
UnifiedStoreKey(dwUID, cOldServerGroupID));
}
if(0 == lpCharacterData)
{
lpCharacterData = CCharacterDataMgr::GetInstance().GetLogoutData(dwCID);
}
if(0 != lpStoreData && 0 != lpCharacterData)
{
switch(lpPktAdminToolSetData->m_cType)
{
case PktAdminToolSetData::OPEN_UPDATE_DATA:
// 세션을 열고 DB에 업데이트하려 시도한다. : 이제는 세션 열 필요 없다. 그냥 한다.
break;
case PktAdminToolSetData::FINISH_UPDATE_DATA:
// 데이터를 DB에 업데이트하고 세션을 닫는다. : 이제는 세션 닫을 필요 없다. 그냥 한다.
break;
case PktAdminToolSetData::CHAR_BASIC_DATA: // 캐릭터 정보. 다음 정보들이 들어감.
// 세션이 운영툴에서 연 세션인지 확인한다. 운영툴에서 연 세션이면, 데이터를 세팅한다.
{
unsigned short* lpSizeArray = reinterpret_cast<unsigned short*>(lpPktAdminToolSetData + 1);
char* lpData = reinterpret_cast<char*>(lpSizeArray + DBUpdateData::MAX_UPDATE_DB);
if(!lpCharacterData->SerializeIn(lpData, lpSizeArray,
dwDataSize - sizeof(unsigned short) * DBUpdateData::MAX_UPDATE_DB, DBUpdateData::MAX_UPDATE_DB))
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴 데이터 세팅 실패 : CHAR_BASIC_DATA",
dwUID, dwCID, GetRemoteAddr().get_addr_string());
wError = PktAdminToolSetData::SETTING_DATA_FAILED;
}
else
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴 데이터 세팅 성공 : CHAR_BASIC_DATA",
dwUID, dwCID, GetRemoteAddr().get_addr_string());
}
}
break;
case PktAdminToolSetData::CHAR_EXTRA_DATA: // 캐릭터 추가 정보들. 다음 정보들이 들어감.
{
unsigned long dwExpectDataSize = sizeof(CHAR_INFOEX) + sizeof(QUEST) +
sizeof(HISTORY) + sizeof(CONFIG) + sizeof(STORE_INFO);
if(dwDataSize == dwExpectDataSize)
{
char* lpCharDataExPos = reinterpret_cast<char*>(lpPktAdminToolSetData + 1);
// CHAR_INFOEX : 캐릭터 추가 정보
lpCharacterData->SetInfoEx(*reinterpret_cast<CHAR_INFOEX*>(lpCharDataExPos));
lpCharDataExPos += sizeof(CHAR_INFOEX);
// QUEST : 퀘스트
lpCharacterData->SetQuest(*reinterpret_cast<QUEST*>(lpCharDataExPos));
lpCharDataExPos += sizeof(QUEST);
// HISTORY : 히스토리
lpCharacterData->SetHistory(*reinterpret_cast<HISTORY*>(lpCharDataExPos));
lpCharDataExPos += sizeof(HISTORY);
// CONFIG : 설정
lpCharacterData->SetConfig(*reinterpret_cast<CONFIG*>(lpCharDataExPos));
lpCharDataExPos += sizeof(CONFIG);
// STORE_INFO : 창고 정보
lpStoreData->SetStoreInfo(*reinterpret_cast<STORE_INFO*>(lpCharDataExPos));
lpCharDataExPos += sizeof(STORE_INFO);
}
else
{
wError = PktAdminToolSetData::SETTING_DATA_FAILED;
}
}
break;
case PktAdminToolSetData::CHAR_FRIEND_DATA: // 캐릭터 친구 정보
if(!lpCharacterData->FriendSerializeIn(
reinterpret_cast<char*>(lpPktAdminToolSetData + 1), dwDataSize))
{
wError = PktAdminToolSetData::SETTING_DATA_FAILED;
}
break;
case PktAdminToolSetData::CHAR_BAN_DATA: // 캐릭터 거부 정보
if(!lpCharacterData->BanSerializeIn(
reinterpret_cast<char*>(lpPktAdminToolSetData + 1), dwDataSize))
{
wError = PktAdminToolSetData::SETTING_DATA_FAILED;
}
break;
case PktAdminToolSetData::STORE_12_DATA: // 창고 1, 2탭 데이터
if(dwDataSize == sizeof(STORE))
{
const STORE& store1 = *reinterpret_cast<STORE*>(lpPktAdminToolSetData + 1);
lpStoreData->SetStore1(store1.Data, store1.dwSize);
}
else
{
wError = PktAdminToolSetData::SETTING_DATA_FAILED;
}
break;
case PktAdminToolSetData::STORE_34_DATA: // 창고 3, 4탭 데이터
if(dwDataSize == sizeof(STORE))
{
const STORE& store2 = *reinterpret_cast<STORE*>(lpPktAdminToolSetData + 1);
lpStoreData->SetStore2(store2.Data, store2.dwSize);
}
else
{
wError = PktAdminToolSetData::SETTING_DATA_FAILED;
}
break;
}
}
}
}
// ItemSerial 업데이트
if(m_AdminItemSerialMgr.SetItemSerial(lpPktAdminToolSetData->m_dwSerial))
{
m_AdminItemSerialMgr.SaveItemSerial(CDBSingleObject::GetInstance(), m_dwServerID);
}
return SendPacket::AdminToolSetDataAck(
GetSendStream(), dwRequestKey, dwUID, dwCID, cType, wError);
}
bool CAdminToolDispatch::ParseGuildPosition(PktGuildPosition* lpPktGuildPosition)
{
using namespace DataStorage;
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwGID = lpPktGuildPosition->m_dwGID;
unsigned long dwCID = lpPktGuildPosition->m_dwCID;
unsigned char cPosition = lpPktGuildPosition->m_cPosition;
unsigned char cType = lpPktGuildPosition->m_cType;
using namespace Guild;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
char* lpBuffer = GetSendStream().GetBuffer(sizeof(PktGuildPosition));
PktGuildPosition* pktSendPacket = NULL;
if(lpBuffer)
{
pktSendPacket = reinterpret_cast<PktGuildPosition*>(lpBuffer);
pktSendPacket->m_cPosition = lpPktGuildPosition->m_cPosition;
pktSendPacket->m_dwCID = lpPktGuildPosition->m_dwCID;
pktSendPacket->m_dwGID = lpPktGuildPosition->m_dwGID;
pktSendPacket->m_cType = lpPktGuildPosition->m_cType;
}
if(!lpGuild)
{
wError = PktGuildPosition::FAIL_GUILD;
}
else
{
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwCID);
if(lpSessionData)
{
wError = PktGuildPosition::FAIL_CONNECT_CHAR;
}
else
{
if(cType==PktGuildPosition::TYPE_POSITION)
{
lpGuild->SetTitle(dwCID, cPosition);
SYSTEMTIME systemTime;
::memset(&systemTime, 0, sizeof(SYSTEMTIME));
GetLocalTime(&systemTime);
if(!DBComponent::GuildDB::UpdateMemberTitle(CDBSingleObject::GetInstance(), dwCID, cPosition, systemTime))
{
wError = PktGuildPosition::FAIL_DB_UPDATE;
}
}
else if(cType==PktGuildPosition::TYPE_MEMBERDELETE)
{
if(!lpGuild->LeaveMember(dwCID))
{
wError = PktGuildPosition::FAIL_MEMBER_DELETE;
}
else
{
using namespace DBAgent::DataStorage;
DBComponent::GameDB::UpdateGuildWarFlag(CDBSingleObject::GetInstance(), dwCID, Creature::WAR_OFF);
}
}
}
}
return GetSendStream().WrapHeader(sizeof(PktGuildPosition), CmdGuildPosition, 0, wError);
}
bool CAdminToolDispatch::ParseItemQtyCheck(PktItemQtyControl* lpPktItemQtyControl)
{
tm* lpTm = localtime(&lpPktItemQtyControl->m_tStartTime);
if(0 == lpTm)
{
ERRLOG2(g_Log, "IP:%15s / StartTime:%d / 아이템 수량 제어 실패 : 시간이 맞지 않습니다",
GetRemoteAddr().get_addr_string(), lpPktItemQtyControl->m_tStartTime);
}
else
{
tm tStartTime = *lpTm;
lpTm = localtime(&lpPktItemQtyControl->m_tEndTime);
if(0 == lpTm)
{
ERRLOG2(g_Log, "IP:%15s / EndTime:%d / 아이템 수량 제어 실패 : 시간이 맞지 않습니다",
GetRemoteAddr().get_addr_string(), lpPktItemQtyControl->m_tEndTime);
}
else
{
tm tEndTime = *lpTm;
if(lpPktItemQtyControl->m_cGroup != CServerSetup::GetInstance().GetServerGroup())
{
ERRLOG3(g_Log, "IP:%15s / CurrentServerGroup:%d / ReceivedServerGroup:%d / 아이템 수량 제어 실패 : 서버 그룹이 맞지 않습니다",
GetRemoteAddr().get_addr_string(), CServerSetup::GetInstance().GetServerGroup(), lpPktItemQtyControl->m_cGroup);
}
else
{
bool bResult = false;
switch(lpPktItemQtyControl->m_cType)
{
case PktItemQtyControl::ADD:
bResult = CGameEventDBMgr::GetInstance().InsertDropItem(
static_cast<unsigned short>(lpPktItemQtyControl->m_dwItemTypeID),
static_cast<unsigned short>(lpPktItemQtyControl->m_dwItemQty),
tStartTime, tEndTime);
DETLOG5(g_Log, "아이템 수량 제어 추가 %s : ID:%u/Qty:%u/StartTime:%d/EndTime:%d",
bResult ? "성공" : "실패",
lpPktItemQtyControl->m_dwItemTypeID, lpPktItemQtyControl->m_dwItemQty,
lpPktItemQtyControl->m_tStartTime, lpPktItemQtyControl->m_tEndTime);
SendPacket::ItemQtyCheck(lpPktItemQtyControl->m_dwItemTypeID,
lpPktItemQtyControl->m_dwItemQty, 0,
lpPktItemQtyControl->m_tStartTime,
lpPktItemQtyControl->m_tEndTime,
PktItemQtyControl::ADD, bResult ? 0 : 1);
break;
case PktItemQtyControl::DEL:
bResult = CGameEventDBMgr::GetInstance().EraseDropItem(
static_cast<unsigned short>(lpPktItemQtyControl->m_dwItemTypeID));
DETLOG5(g_Log, "아이템 수량 제어 삭제 %s : ID:%u/Qty:%u/StartTime:%d/EndTime:%d",
bResult ? "성공" : "실패",
lpPktItemQtyControl->m_dwItemTypeID, lpPktItemQtyControl->m_dwItemQty,
lpPktItemQtyControl->m_tStartTime, lpPktItemQtyControl->m_tEndTime);
SendPacket::ItemQtyCheck(lpPktItemQtyControl->m_dwItemTypeID,
lpPktItemQtyControl->m_dwItemQty, 0,
lpPktItemQtyControl->m_tStartTime, lpPktItemQtyControl->m_tEndTime,
PktItemQtyControl::DEL, bResult ? 0 : 1);
break;
case PktItemQtyControl::STATUS_REQUEST:
DETLOG0(g_Log, "아이템 수량 제어 상태 요청");
CGameEventDBMgr::GetInstance().SendDropItemInfo();
break;
}
}
}
}
return true;
}
class CSendNameChanged
{
public:
CSendNameChanged(unsigned long dwUID, unsigned long dwCID, const char* szChangedName,
unsigned char cNameChangeCount, unsigned short usError)
: m_dwUID(dwUID), m_dwCID(dwCID),
m_cNameChangeCount(cNameChangeCount),
m_usError(usError)
{
strncpy(m_szChangedName, szChangedName, CHAR_INFOST::MAX_NAME_LEN);
m_szChangedName[ CHAR_INFOST::MAX_NAME_LEN - 1 ] = 0;
}
bool operator () (unsigned long dwServerID, CPacketDispatch& dispatch)
{
return GameClientSendPacket::SendCharNameChange(
static_cast<CRylServerDispatch&>(dispatch).GetSendStream(),
m_dwUID, m_dwCID, m_szChangedName, m_cNameChangeCount, NULL, m_usError);
}
private:
unsigned long m_dwUID;
unsigned long m_dwCID;
unsigned char m_cNameChangeCount;
unsigned short m_usError;
char m_szChangedName[CHAR_INFOST::MAX_NAME_LEN];
};
bool CAdminToolDispatch::ParseAdminToolChangeName(PktAdminToolGetData* lpPktAdminToolGetData)
{
unsigned long dwUID = lpPktAdminToolGetData->m_dwUID;
unsigned long dwCID = lpPktAdminToolGetData->m_dwCID;
unsigned long dwRequestKey = lpPktAdminToolGetData->m_dwRequestKey;
const char* szChangeName = lpPktAdminToolGetData->m_szName;
unsigned short usError = 0;
using namespace DBAgent::DataStorage;
CSessionData* lpSessionData =
CSessionDataMgr::GetInstance().GetCharLoadedSession(dwCID);
CCharacterData* lpCharacterData = 0;
if (0 == lpSessionData ||
lpSessionData->GetUID() != dwUID ||
lpSessionData->GetCID() != dwCID ||
(0 == (lpCharacterData = lpSessionData->GetCharacterData())) ||
dwCID != lpCharacterData->GetCID())
{
lpCharacterData = CCharacterDataMgr::GetInstance().GetLogoutData(dwCID);
}
if (0 != lpCharacterData)
{
unsigned long dwResult = 0;
if (DBComponent::GameDB::ChangeCharName(
CDBSingleObject::GetInstance(), dwCID, szChangeName, dwResult))
{
if (0 == dwResult)
{
// 이름을 바꾼다.
CHAR_INFOST charInfoST = lpCharacterData->GetInfo();
strncpy(charInfoST.Name, szChangeName, CHAR_INFOST::MAX_NAME_LEN);
charInfoST.Name[CHAR_INFOST::MAX_NAME_LEN - 1] = 0;
lpCharacterData->SetInfo(charInfoST, true);
}
else if(1 == dwResult)
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / 운영툴로 캐릭터 이름 바꾸기 실패 : 이름이 이미 있습니다",
dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_ALREADY_USE_NAME;
}
else
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / dwResult:%10u / 운영툴로 캐릭터 이름 바꾸기 실패 : 알 수 없는 dwResult값입니다",
dwUID, dwCID, szChangeName, dwResult);
usError = PktCharNameChange::ERR_SERVER;
}
}
else
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / 운영툴로 캐릭터 이름 바꾸기 실패 : DB호출 에러",
dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_SERVER;
}
}
else
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / "
"운영툴로 캐릭터 이름 바꾸기 실패 : 해당하는 캐릭터를 찾을 수 없습니다.", dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_CANNOT_FIND_CHARACTER;
}
if (0 != lpSessionData && 0 != lpCharacterData && 0 == usError)
{
// 모든 게임 서버에 전송한다.
DBAgent::CGameDispatch::GetDispatchTable().Process(
CSendNameChanged(dwUID, dwCID, szChangeName,
lpCharacterData->GetInfoEx().cNameChangeCount, usError));
}
// 운영툴로 Ack를 전송한다.
return SendPacket::AdminToolGetDataAck(GetSendStream(),
PktAdminToolGetData::CHANGE_CHAR_NAME, dwRequestKey, dwUID, dwCID, 0, 0, usError);
}
bool GetUIDCIDFromName(const char* szName, unsigned long& dwUID_Out,
unsigned long& dwCID_Out, unsigned char& cOldServerGroupID)
{
#pragma pack(1)
struct UIDCID
{
unsigned long dwUID;
unsigned long dwCID;
unsigned char cOldServerGroupID;
};
#pragma pack()
UIDCID uidcid;
uidcid.dwUID = 0;
uidcid.dwCID = 0;
const int MAX_BUFFER = 1024;
char szQuery[MAX_BUFFER] = { 0, };
int nLength = _snprintf(szQuery, MAX_BUFFER - 1, "dbo.GetUIDCIDFromName '%s'", szName);
szQuery[MAX_BUFFER - 1] = 0;
if(0 < nLength)
{
szQuery[nLength] = 0;
if(CDBSingleObject::GetInstance().ExecuteQueryGetData(szQuery, &uidcid))
{
dwUID_Out = uidcid.dwUID;
dwCID_Out = uidcid.dwCID;
cOldServerGroupID = uidcid.cOldServerGroupID;
return true;
}
}
ERRLOG2(g_Log, "캐릭터 이름으로 UID / CID 얻어 오는 쿼리에 실패했습니다. %s : %s",
CDBSingleObject::GetInstance().GetErrorString(), szQuery);
return false;
}
}

View File

@@ -0,0 +1,62 @@
#ifndef _DBAGENT_SERVER_ADMIN_TOOL_DISPATCH_H_
#define _DBAGENT_SERVER_ADMIN_TOOL_DISPATCH_H_
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <Item/ItemSerialMgr.h>
// forward decl.
struct PktSL;
struct PktUK;
struct PktItemQtyControl;
struct PktAdminToolGetData;
struct PktAdminToolSetData;
struct PktGuildPosition;
namespace DBAgent
{
class CAdminToolDispatch : public CRylServerDispatch
{
public:
static CMultiDispatch& GetDispatchTable();
enum Const
{
MAX_PACKET_DISPATCH_PER_PULSE = 100,
MAX_STREAM_BUFFER_SIZE = 16000
};
CAdminToolDispatch(CSession& Session);
virtual ~CAdminToolDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
private:
bool ParseServerLogin(PktSL* lpPktSL);
bool ParseServerLogout(PktBase* lpPktBase);
bool ParseUserKill(PktUK* lpPktUK);
bool ParseGetData(PktBase* lpPktBase);
bool ParseSetData(PktBase* lpPktBase);
bool ParseItemQtyCheck(PktItemQtyControl* lpPktItemQtyControl); // 이벤트 아이템 수량 관련 패킷
bool ParseAdminToolGetData(PktAdminToolGetData* lpPktAdminToolGetData); // 현재 운영툴(AdminTool)
bool ParseAdminToolSetData(PktAdminToolSetData* lpPktAdminToolSetData); // 현재 운영툴(AdminTool)
bool ParseAdminToolChangeName(PktAdminToolGetData* lpPktAdminToolGetData); // 운영툴로 캐릭터 이름 바꾸기
bool ParseGuildPosition(PktGuildPosition* lpPktGuildPosition); // 길드 포지션 설정.
Item::CItemSerialMgr m_AdminItemSerialMgr;
unsigned long m_dwServerID;
};
}
#endif

View File

@@ -0,0 +1,232 @@
#include "stdafx.h"
#include "AuthDispatch.h"
#include <Log/ServerLog.h>
#include <Utility/Setup/ServerSetup.h>
#include <Network/Address/INET_Addr.h>
#include <Network/SendPacket/SendServerInfo.h>
#include <Network/SendPacket/SendLoginout.h>
#include <Network/ParsePacket/ParseCharManage.h>
#include <Network/ParsePacket/ParseGuild.h>
#include <Network/ParsePacket/ParseParty.h>
#include <Network/ParsePacket/ParseMoveZone.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Dispatch/LoginDispatch.h>
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <DataStorage/SessionData.h>
#include <DataStorage/SessionDataMgr.h>
namespace DBAgent
{
CSingleDispatch& CAuthDispatch::GetDispatchTable()
{
static CSingleDispatch authDispatch;
return authDispatch;
}
CAuthDispatch::CAuthDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE),
m_dwServerID(0),
m_nUserNum(1)
{
}
CAuthDispatch::~CAuthDispatch()
{
}
void CAuthDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/AuthServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
}
void CAuthDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/AuthServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
if(0 != m_dwServerID)
{
GetDispatchTable().RemoveDispatch(this);
if(0LL != m_AuthItemSerialMgr.GetItemSerial())
{
// 아이템 시리얼 DB에 저장
m_AuthItemSerialMgr.SaveItemSerial(
CDBSingleObject::GetInstance(), m_dwServerID);
}
GET_SINGLE_DISPATCH(lpLoginDispatch, CLoginDispatch,
CLoginDispatch::GetDispatchTable());
if(0 != lpLoginDispatch)
{
// 로그인서버로 서버 버전 업데이트
SendPacket::UpdateServerVersion(lpLoginDispatch->GetSendStream());
}
// 현재 서버에 로그인된 사람을 전부 내려버린다.
DataStorage::CSessionDataMgr::GetInstance().SessionCloseCurrentServer(m_dwServerID);
}
}
bool CAuthDispatch::DispatchPacket(PktBase* lpPktBase)
{
// Auth 에서 보낸 패킷을 처리하는 부분이다.
bool bResult = false;
PktBase::CMDType cCmd = lpPktBase->GetCmd();
switch(cCmd)
{
case CmdSysServerLogin: bResult = ParseServerLogin(static_cast<PktSL*>(lpPktBase)); break;
case CmdSysServerLogout: bResult = ParseServerLogout(lpPktBase); break;
case CmdUserKill: bResult = ParseUserKill(static_cast<PktUK*>(lpPktBase)); break;
case CmdDBGetData:
{
PktDD* pkDD = static_cast<PktDD*>(lpPktBase);
// DETLOG4(g_Log, "SS:0x%08x/DP:0x%08x/Len:0x%08x/CMD:0x%04x : CmdDBGetData", &GetSession(), this, pkDD->GetLen(), pkDD->m_wCmd);
bResult = ParseCharManage::Parse(GetSendStream(), m_dwServerID,
m_AuthItemSerialMgr, pkDD);
}
break;
case CmdAgentZone: bResult = ParseMoveZone::Parse(GetSendStream(), static_cast<PktDD*>(lpPktBase)); break;
case CmdAgentParty: bResult = ParseParty::Parse(GetSendStream(), lpPktBase); break;
case CmdGuildCmd: bResult = ParseGuild::GuildCmd(GetSendStream(), lpPktBase); break;
case CmdUnifiedCharSelect:
bResult = ParseCharManage::UnifiedCharSelect(GetSendStream(), lpPktBase);
break;
default:
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ 인증서버 패킷 처리 실패 : 없는 커맨드입니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
bResult = true;
break;
}
if(!bResult)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ 인증서버 패킷 처리 실패 : 처리를 실패했습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
}
return true;
}
bool CAuthDispatch::ParseServerLogin(PktSL* lpPktSL)
{
m_dwServerID = lpPktSL->m_dwServerID;
INFLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 인증서버 연결 시도 : 패킷 받음",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
GET_SINGLE_DISPATCH(lpAuthDispatch,
CAuthDispatch, GetDispatchTable());
if(0 != lpAuthDispatch)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 인증서버 연결 실패 : 이미 연결이 있습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
}
else
{
// Dispatch 세팅.
GetDispatchTable().SetDispatch(this);
// 아이템 시리얼 로드.
if(!m_AuthItemSerialMgr.LoadItemSerial(CDBSingleObject::GetInstance(), m_dwServerID))
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/인증서버 연결 실패 : 아이템 시리얼 로드 실패. 접속을 끊습니다.",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
return false;
}
GET_SINGLE_DISPATCH(lpLoginDispatch, CLoginDispatch,
CLoginDispatch::GetDispatchTable());
if(0 != lpLoginDispatch)
{
// 로그인서버로 서버 버전 업데이트
SendPacket::UpdateServerVersion(lpLoginDispatch->GetSendStream());
}
return SendPacket::ServerLoginAck(m_SendStream,
m_dwServerID, m_AuthItemSerialMgr.GetItemSerial());
}
return true;
}
bool CAuthDispatch::ParseServerLogout(PktBase* lpPktBase)
{
// 받은 패킷 그대로 돌려 준다.
char* lpBuffer = m_SendStream.GetBuffer(sizeof(PktBase));
if(0 != lpBuffer)
{
return m_SendStream.WrapHeader(sizeof(PktBase), CmdSysServerLogout, 0, 0);
}
return false;
}
bool CAuthDispatch::ParseUserKill(PktUK* lpPktUK)
{
// 유저 죽이기를 실패해서, Ack로 오는 경우이다.
if(2 == lpPktUK->GetError())
{
DataStorage::CSessionData* lpSessionData =
DataStorage::CSessionDataMgr::GetInstance().GetOpenSession(lpPktUK->m_dwUserID);
if(0 != lpSessionData &&
DataStorage::CSessionData::SE_USER_ENABLED == lpSessionData->GetSessionState())
{
if(lpSessionData->GetServerID() == lpPktUK->m_dwServerID)
{
DataStorage::CSessionDataMgr::GetInstance().SessionCloseWithLogout(
lpPktUK->m_dwUserID, lpPktUK->m_dwServerID);
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 게임서버 세션 강제 종료 : 캐릭터 죽이기 실패",
lpPktUK->m_dwUserID, lpPktUK->m_dwServerID);
}
else
{
ERRLOG3(g_Log, "UID:%10u / FromServerID:0x%08X / TargetServerID:0x%08X / "
"게임서버 세션 강제 종료 실패 : 실패 서버와 죽이기 요청 서버가 다름",
lpPktUK->m_dwUserID, lpPktUK->m_dwServerID, lpSessionData->GetServerID());
}
}
}
return true;
}
}

View File

@@ -0,0 +1,52 @@
#ifndef _DBAGENT_SERVER_AUTH_DISPATCH_H_
#define _DBAGENT_SERVER_AUTH_DISPATCH_H_
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Item/ItemSerialMgr.h>
// forward decl.
struct PktSL;
struct PktUK;
struct PktDD;
namespace DBAgent
{
class CAuthDispatch : public CRylServerDispatch
{
public:
static CSingleDispatch& GetDispatchTable();
enum Const
{
MAX_PACKET_DISPATCH_PER_PULSE = 100,
MAX_STREAM_BUFFER_SIZE = 16000
};
CAuthDispatch(CSession& Session);
virtual ~CAuthDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
void IncUserNum() { ++m_nUserNum; }
void DecUserNum() { --m_nUserNum; }
int GetUserNum() const { return (m_nUserNum < 1) ? 1 : m_nUserNum; }
private:
bool ParseServerLogin(PktSL* lpPktSL);
bool ParseServerLogout(PktBase* lpPktBase);
bool ParseUserKill(PktUK* lpPktUK);
unsigned long m_dwServerID;
int m_nUserNum;
Item::CItemSerialMgr m_AuthItemSerialMgr;
};
}
#endif

View File

@@ -0,0 +1,126 @@
#include "stdafx.h"
#include "ChatDispatch.h"
#include <Log/ServerLog.h>
#include <Network/Address/INET_Addr.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/SendPacket/SendServerInfo.h>
namespace DBAgent
{
CSingleDispatch& CChatDispatch::GetDispatchTable()
{
static CSingleDispatch chatDispatch;
return chatDispatch;
}
CChatDispatch::CChatDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE)
{
}
CChatDispatch::~CChatDispatch()
{
}
void CChatDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ChatServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
}
void CChatDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ChatServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
if(0 != m_dwServerID)
{
GetDispatchTable().RemoveDispatch(this);
}
}
bool CChatDispatch::DispatchPacket(PktBase* lpPktBase)
{
bool bResult = false;
PktBase::CMDType cCmd = lpPktBase->GetCmd();
switch(cCmd)
{
case CmdSysServerLogin:
bResult = ParseServerLogin(static_cast<PktSL*>(lpPktBase));
break;
case CmdSysServerLogout:
bResult = ParseServerLogout(lpPktBase);
break;
default:
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ 채팅서버 패킷 처리 실패 : 없는 커맨드입니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
bResult = true;
break;
}
if(!bResult)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ 채팅서버 패킷 처리 실패 : 처리를 실패했습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
}
return true;
}
bool CChatDispatch::ParseServerLogin(PktSL* lpPktSL)
{
m_dwServerID = lpPktSL->m_dwServerID;
INFLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 채팅서버 연결 시도 : 패킷 받음",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
GET_SINGLE_DISPATCH(lpChatDispatch,
CChatDispatch, GetDispatchTable());
if(0 != lpChatDispatch)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/ 채팅서버 연결 실패 : 이미 연결이 있습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
}
else
{
// Dispatch 세팅.
GetDispatchTable().SetDispatch(this);
return SendPacket::ServerLoginAck(m_SendStream, m_dwServerID, 0LL);
}
return true;
}
bool CChatDispatch::ParseServerLogout(PktBase* lpPktBase)
{
// 받은 패킷 그대로 돌려 준다.
char* lpBuffer = m_SendStream.GetBuffer(sizeof(PktBase));
if(0 != lpBuffer)
{
return m_SendStream.WrapHeader(sizeof(PktBase), CmdSysServerLogout, 0, 0);
}
return false;
}
}

View File

@@ -0,0 +1,42 @@
#ifndef _DBAGENT_SERVER_CHAT_DISPATCH_H_
#define _DBAGENT_SERVER_CHAT_DISPATCH_H_
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
// forward decl.
struct PktSL;
namespace DBAgent
{
class CChatDispatch : public CRylServerDispatch
{
public:
static CSingleDispatch& GetDispatchTable();
enum Const
{
MAX_PACKET_DISPATCH_PER_PULSE = 100,
MAX_STREAM_BUFFER_SIZE = 16000
};
CChatDispatch(CSession& Session);
virtual ~CChatDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
private:
bool ParseServerLogin(PktSL* lpPktSL);
bool ParseServerLogout(PktBase* lpPktBase);
unsigned long m_dwServerID;
};
}
#endif

View File

@@ -0,0 +1,827 @@
#include "stdafx.h"
#include "GameDispatch.h"
#include <Log/ServerLog.h>
#include <Utility/Setup/ServerSetup.h>
#include <Network/Address/INET_Addr.h>
#include <Network/Stream/SendStream.h>
#include <Network/Packet/PacketDispatchTable.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Packet/PacketStruct/ServerLogPacket.h>
#include <Network/Packet/PacketStruct/CharAdminPacket.h>
#include <Network/ParsePacket/ParseMoveZone.h>
#include <Network/ParsePacket/ParseCharManage.h>
#include <Network/ParsePacket/ParseCharUpdate.h>
#include <Network/ParsePacket/ParseParty.h>
#include <Network/ParsePacket/ParseCastle.h>
#include <Network/ParsePacket/ParseGuild.h>
#include <Network/SendPacket/SendServerInfo.h>
#include <Network/Dispatch/GameClient/SendCharAdmin.h>
#include <Creature/Character/CharacterClass.h>
#include <Creature/StatueDBMgr.h>
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <DataStorage/SessionData.h>
#include <DataStorage/SessionDataMgr.h>
#include <Castle/CastleDBMgr.h>
#include <GameTime/GameTimeDBMgr.h>
#include <Creature/Siege/SiegeObjectDBMgr.h>
#include <Community/Guild/GuildDBMgr.h>
#include <Ranking/RankingDBMgr.h>
#include <GameEvent/GiveItemMgr.h>
#include <DataStorage/SessionDataMgr.h>
#include <DataStorage/CharacterDataMgr.h>
#include <Map/FieldMap/MineralVeinDBMgr.h>
#include <Ranking/RankingMgr.h>
#include <Community/Party/PartyDBMgr.h>
namespace DBAgent
{
typedef bool (*GameDispatchFunc) (CSendStream& SendStream, PktBase* lpPktBase);
// forward delc.
bool ParseServerLog(CSendStream& SendStream, PktBase* lpPktBase);
class CGameDispatchTable : public CPacketDispatchTable<GameDispatchFunc>
{
public:
static CGameDispatchTable& GetInstance();
private:
CGameDispatchTable();
};
CGameDispatchTable& CGameDispatchTable::GetInstance()
{
static CGameDispatchTable gameDispatchTable;
return gameDispatchTable;
}
CGameDispatchTable::CGameDispatchTable()
: CPacketDispatchTable<GameDispatchFunc>(UCHAR_MAX)
{
// 데이터 업데이트 관련
AddDispatch(CmdDepositUpdate, ParseCharUpdate::UpdateDepositDB);
AddDispatch(CmdDeposit, ParseCharUpdate::UpdateDeposit);
AddDispatch(CmdFriendDB, ParseCharUpdate::UpdateFriendDB);
AddDispatch(CmdQuestDB, ParseCharUpdate::UpdateQuestDB);
AddDispatch(CmdConfigInfoDB, ParseCharUpdate::UpdateConfigInfoDB);
// 존이동 관련
AddDispatch(CmdAgentZone, ParseMoveZone::Parse);
// 파티 관련
AddDispatch(CmdAgentParty, ParseParty::Parse);
// 배틀그라운드 관련
AddDispatch(CmdBGServerCharSlot, ParseCharManage::BGServerCharSlot);
// 로그 관련
AddDispatch(CmdServerLog, ParseServerLog);
// 길드 관련
AddDispatch(CmdCreateGuild, ParseGuild::CreateGuild);
AddDispatch(CmdGuildCmd, ParseGuild::GuildCmd);
AddDispatch(CmdGuildMark, ParseGuild::GuildMark);
AddDispatch(CmdGuildLevel, ParseGuild::GuildLevel);
AddDispatch(CmdGuildRelation, ParseGuild::GuildRelation);
AddDispatch(CmdGuildInclination, ParseGuild::GuildInclination);
AddDispatch(CmdGuildRight, ParseGuild::SetGuildRight);
AddDispatch(CmdGuildSafe, ParseGuild::GuildSafe);
AddDispatch(CmdGuildMemberInfoUpdate, ParseGuild::GuildMemberInfoUpdate);
// 공성 관련
AddDispatch(CmdCreateCamp, ParseCastle::CreateCamp);
AddDispatch(CmdCreateSiegeArms, ParseCastle::CreateSiegeArms);
AddDispatch(CmdCastleCmd, ParseCastle::CastleCmd);
AddDispatch(CmdCampCmd, ParseCastle::CampCmd);
AddDispatch(CmdSiegeArmsCmd, ParseCastle::SiegeArmsCmd);
AddDispatch(CmdCastleRight, ParseCastle::SetCastleRight);
AddDispatch(CmdCampRight, ParseCastle::SetCampRight);
AddDispatch(CmdCampMessage, ParseCastle::CampMessage);
AddDispatch(CmdMiningCampMineralInfo, ParseCastle::MiningCampMineralInfo);
AddDispatch(CmdFertilityInfo, ParseCastle::FertilityInfo);
AddDispatch(CmdCampShopInfo, ParseCastle::CampShopInfo);
AddDispatch(CmdCastleTaxMove, ParseCastle::CastleTaxMove);
AddDispatch(CmdCastleMineralInfo, ParseCastle::CastleMineralInfo);
AddDispatch(CmdWarOnOff, ParseCastle::WarOnOff);
AddDispatch(CmdStatueCmd, ParseCastle::StatueCmd);
AddDispatch(CmdAdminCommandLog, ParseCharAdmin::AdminCommandLog);
AddDispatch(CmdRealmPoint, ParseCastle::RealmPoint);
// 듀얼 관련.
AddDispatch(CmdSaveEnemy, ParseCharUpdate::SaveEnemy);
// 조이스틱 관련.
AddDispatch(CmdKeyInfo, ParseCharUpdate::UpdateKeyInfo);
// 아이템 관련
AddDispatch(CmdCharUseCashItem, ParseCharUpdate::UseCashItem);
AddDispatch(CmdExtraEvent, ParseCharUpdate::ExtraEvent);
}
CMultiDispatch& CGameDispatch::GetDispatchTable()
{
static CMultiDispatch gameDispatch;
return gameDispatch;
}
CGameDispatch::CGameDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE),
m_nHumanNum(1),
m_nAkhanNum(1),
m_dwServerID(0)
{
}
CGameDispatch::~CGameDispatch()
{
}
void CGameDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/GameServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
}
void CGameDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/GameServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
if(0 != m_dwServerID)
{
GetDispatchTable().RemoveDispatch(m_dwServerID);
if(0LL != m_GameItemSerialMgr.GetItemSerial())
{
// 아이템 시리얼 DB에 저장
m_GameItemSerialMgr.SaveItemSerial(
CDBSingleObject::GetInstance(), m_dwServerID);
}
// 채널 정보 업데이트
DBAgent::SendPacket::UpdateChannelAllServer();
// 현재 서버에 로그인된 사람을 전부 내려버린다.
DataStorage::CSessionDataMgr::GetInstance().SessionCloseCurrentServer(m_dwServerID);
}
}
bool CGameDispatch::DispatchPacket(PktBase* lpPktBase)
{
// 게임서버에서 DBAgent로 보내는 패킷정보
PktBase::CMDType cCmd =lpPktBase->GetCmd();
bool bResult = false;
GameDispatchFunc lpDispatchFunc = 0;
CSendStream& SendStream = GetSendStream();
switch(cCmd)
{
// 로그인 / 로그아웃 / 데이터 업데이트
case CmdDBUpdateData:
// 유저가 로그인하거나 로그아웃할때 여기로 메시지를 보낸다.
// 여기서 타임DB를 업데이트 하거나 한다.
bResult = ParseCharUpdate::Parse(SendStream, m_dwServerID,
m_GameItemSerialMgr, static_cast<PktDBUpdate*>(lpPktBase));
break;
case CmdSysServerLogin: bResult = ServerLogin(lpPktBase); break; // 서버 로그인
case CmdSysServerLogout: bResult = ServerLogout(lpPktBase); break; // 서버 로그아웃
case CmdUserKill: bResult = UserKillAck(lpPktBase); break; // 유저 죽이기
case CmdCharAdminCmd: bResult = CharAdminCmd(lpPktBase); break; // 운영자 명령
case CmdGiveItemToTempInven: bResult = GiveItemToTempInven(lpPktBase); break; // 임시인벤으로 아이템 주기
case CmdCharNameChange: bResult = ChangeName(lpPktBase); break; // 캐릭터 이름을 바꾼다
default:
// 기타 명령(테이블에서 검색)
lpDispatchFunc = CGameDispatchTable::GetInstance().GetDispatch(cCmd);
if(0 != lpDispatchFunc)
{
bResult = lpDispatchFunc(SendStream, lpPktBase);
}
else
{
ERRLOG5(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ServerID:0x%08X / "
"게임서버 패킷 처리 실패 : 없는 커맨드입니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd, m_dwServerID);
bResult = true;
}
break;
}
if(!bResult)
{
ERRLOG5(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ServerID:0x%08X / 게임서버 패킷 처리 실패 : 처리를 실패했습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd, m_dwServerID);
}
return true;
}
bool CGameDispatch::ServerLogin(PktBase* lpPktBase)
{
PktSL* lpPktSL = static_cast<PktSL*>(lpPktBase);
m_dwServerID = lpPktSL->m_dwServerID;
INFLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/게임서버 연결 시도 : 패킷 받음",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
GET_MULTI_DISPATCH(lpGameDispatch, m_dwServerID,
CGameDispatch, GetDispatchTable());
if(0 != lpGameDispatch)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/게임서버 연결 실패 : 이미 연결이 있습니다. 접속을 끊습니다.",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
}
else
{
// Dispatch 세팅.
GetDispatchTable().SetDispatch(m_dwServerID, this);
// 아이템 시리얼 로드.
if(!m_GameItemSerialMgr.LoadItemSerial(CDBSingleObject::GetInstance(), m_dwServerID))
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/ServerID:0x%08X/게임서버 연결 실패 : 아이템 시리얼 로드 실패. 접속을 끊습니다.",
&GetSession(), this, GetRemoteAddr().get_addr_string(), m_dwServerID);
CloseSession();
return false;
}
CSendStream& SendStream = GetSendStream();
// 길드 정보 업데이트
Guild::CGuildDBMgr::GetInstance().SendGuildDBList(SendStream);
SERVER_ID serverID;
serverID.dwID = m_dwServerID;
/// 성 및 캠프, 공성병기 관련 정보 업데이트.
Castle::CCastleDBMgr::GetInstance().SendCastleInfo(SendStream, serverID.GetZone(), serverID.GetChannel());
CGameTimeDBMgr::GetInstance().SendGameTimeInfo(GameTime::TYPE_GAMESERVER_LOGIN, true, true, true, true, true);
CSiegeObjectDBMgr::GetInstance().SendWorldWeaponInfo(SendStream, serverID.GetZone(), serverID.GetChannel());
CSiegeObjectDBMgr::GetInstance().SendCampInfo(SendStream, serverID.GetZone(), serverID.GetChannel());
CSiegeObjectDBMgr::GetInstance().SendSiegeArmsInfo(SendStream, serverID.GetZone(), serverID.GetChannel());
// 컨텐츠 : 다크 카나번 국가 전쟁
if (true == CServerSetup::GetInstance().UseContents(GameRYL::STONE_BATTLE))
{
// 석상 정보 업데이트
// 주의 : 성 정보가 석상 정보보다 먼저 보내져야한다.!!
// 성에 의해 석상 인챈트 효과가 영향을 받기 때문이다.!!
if (SERVER_ID::STONE_WAR1 <= serverID.GetZone() && serverID.GetZone() <= SERVER_ID::STONE_WAR3)
{
CStatueDBMgr::GetInstance().SendStatueInfo(SendStream, serverID.GetChannel());
}
}
/*
// 컨텐츠 : 신규존
if (true == CServerSetup::GetInstance().UseContents(GameRYL::NEWZONE_ZONE9))
{
// 생명축출기 정보 업데이트
// 주의 : 성 정보가 생명축출기 정보보다 먼저 보내져야한다.!!
if (serverID.GetZone() == SERVER_ID::ZONE9)
{
CStatueDBMgr::GetInstance().SendStatueInfo(SendStream, serverID.GetChannel());
}
}
*/
// 지력 정보 업데이트
CMineralVeinDBMgr::GetInstance().SendFertilityInfo(SendStream, serverID.GetZone(), serverID.GetChannel());
// 채널 정보 업데이트
DBAgent::SendPacket::UpdateChannelAllServer();
// 랭킹 정보 업데이트
CRankingDBMgr::GetInstance().SendRankingInfo(SendStream);
// 파티 정보가 있으면 보내준다 //
CPartyDBMgr::GetInstance().SendToGameServerPartyData(SendStream);
// 서버 로그인 Ack보냄.
return SendPacket::ServerLoginAck(m_SendStream,
m_dwServerID, m_GameItemSerialMgr.GetItemSerial());
}
return true;
}
bool CGameDispatch::ServerLogout(PktBase* lpPktBase)
{
// 받은 패킷 그대로 돌려 준다.
char* lpBuffer = m_SendStream.GetBuffer(sizeof(PktBase));
if(0 != lpBuffer)
{
return m_SendStream.WrapHeader(sizeof(PktBase), CmdSysServerLogout, 0, 0);
}
return false;
}
bool CGameDispatch::UserKillAck(PktBase* lpPktBase)
{
// 유저 죽이기를 실패해서, Ack로 오는 경우이다.
PktUK* lpPktUK = static_cast<PktUK*>(lpPktBase);
if(2 == lpPktUK->GetError())
{
using namespace DataStorage;
CSessionData* lpSessionData =
CSessionDataMgr::GetInstance().GetOpenSession(lpPktUK->m_dwUserID);
if(0 != lpSessionData &&
CSessionData::SE_CHAR_ENABLED == lpSessionData->GetSessionState())
{
if(lpSessionData->GetServerID() == lpPktUK->m_dwServerID)
{
CSessionDataMgr::GetInstance().SessionCloseWithLogout(
lpPktUK->m_dwUserID, lpPktUK->m_dwServerID);
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 게임서버 세션 강제 종료 : 유저 죽이기 실패",
lpPktUK->m_dwUserID, lpPktUK->m_dwServerID);
}
else
{
ERRLOG3(g_Log, "UID:%10u / FromServerID:0x%08X / TargetServerID:0x%08X / "
"게임서버 세션 강제 종료 실패 : 실패 서버와 죽이기 요청 서버가 다름",
lpPktUK->m_dwUserID, lpPktUK->m_dwServerID, lpSessionData->GetServerID());
}
}
}
return true;
}
bool CGameDispatch::CharAdminCmd(PktBase* lpPktBase)
{
PktAdmin* lpPktAdmin = static_cast<PktAdmin*>(lpPktBase);
PktAdmin pktSendAdmin;
// 패킷 내용을 그대로 복사.
memcpy(&pktSendAdmin, lpPktAdmin, sizeof(PktAdmin));
// 중계서버 강제 종료
/*if(lpPktAdmin->m_usCmd == PktAdmin::DBAGENT_KILL)
{
int nZero = 0;
int nError = 10 / nZero;
*reinterpret_cast<int*>(nError) = 0xFFFFFFFF;
}*/
// 추적한 위치 좌표를, 게임 서버로부터 받은 경우라면...
if (lpPktAdmin->m_usCmd == PktAdmin::REQUEST_TRACE_POS)
{
// 해당 게임 서버에게만 TRACE 명령 전송
pktSendAdmin.m_usCmd = PktAdmin::TRACE_CHAR;
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::GameServer;
serverID.sID.Group = CServerSetup::GetInstance().GetServerGroup();
serverID.sID.Channel = lpPktAdmin->m_ZoneInfo.m_cChannel;
serverID.sID.ID = lpPktAdmin->m_ZoneInfo.m_cZone;
GET_MULTI_DISPATCH(lpGameDispatch, serverID.dwID,
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 != lpGameDispatch)
{
serverID.dwID = m_dwServerID;
// 게임 서버로 보낼때는 channel 이 -1 이어야 한다. -_-;
pktSendAdmin.m_ZoneInfo.m_cZone = serverID.GetZone();
pktSendAdmin.m_ZoneInfo.m_cChannel = -1;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktSendAdmin),
sizeof(PktAdmin), CmdCharAdminCmd, 0, 0))
{
lpGameDispatch->GetSendStream().PutBuffer(
reinterpret_cast<char*>(&pktSendAdmin), sizeof(PktAdmin), CmdCharAdminCmd);
}
}
return true;
}
else if (lpPktAdmin->m_usCmd == PktAdmin::TRACE_CHAR)
{
using namespace DBAgent::DataStorage;
// 캐릭터가 로그아웃한 상태라면
if (false == CSessionDataMgr::GetInstance().IsLoadedChar(lpPktAdmin->m_stName))
{
// 해당 게임 서버에게 해당 캐릭터가 로그아웃 했다는 정보를 보낸다.
pktSendAdmin.m_usCmd = PktAdmin::TRACE_CHAR;
GET_MULTI_DISPATCH(lpGameDispatch, m_dwServerID,
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 != lpGameDispatch)
{
// 게임 서버로 보낼때는 channel 이 -1 이어야 한다. -_-;
pktSendAdmin.m_ZoneInfo.m_cChannel = -1;
pktSendAdmin.m_Position.fPointX = 0.0f;
pktSendAdmin.m_Position.fPointY = 0.0f;
pktSendAdmin.m_Position.fPointZ = 0.0f;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktSendAdmin),
sizeof(PktAdmin), CmdCharAdminCmd, 0, PktAdmin::E_LOGOUT_CHAR))
{
lpGameDispatch->GetSendStream().PutBuffer(
reinterpret_cast<char*>(&pktSendAdmin), sizeof(PktAdmin), CmdCharAdminCmd);
}
}
}
else
{
pktSendAdmin.m_usCmd = PktAdmin::REQUEST_TRACE_POS;
SERVER_ID serverID;
serverID.dwID = m_dwServerID;
// TRACE 시켜야 할 캐릭터가 현재 있는 존의 번호를 기억해둔다.
pktSendAdmin.m_ZoneInfo.m_cZone = serverID.GetZone();
pktSendAdmin.m_ZoneInfo.m_cChannel = 0;
}
}
/*
else if (lpPktAdmin->m_usCmd == PktAdmin::INFO_CHAR)
{
using namespace DBAgent::DataStorage;
// 캐릭터가 로그아웃한 상태라면
if (false == CSessionDataMgr::GetInstance().IsLoadedChar(lpPktAdmin->m_stName))
{
pktSendAdmin.m_usCmd = PktAdmin::INFO_CHAR;
GET_MULTI_DISPATCH(lpGameDispatch, m_dwServerID,
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 != lpGameDispatch)
{
// 게임 서버로 보낼때는 channel 이 -1 이어야 한다. -_-;
pktSendAdmin.m_ZoneInfo.m_cChannel = -1;
pktSendAdmin.m_Position.fPointX = 0.0f;
pktSendAdmin.m_Position.fPointY = 0.0f;
pktSendAdmin.m_Position.fPointZ = 0.0f;
if (PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktSendAdmin),
sizeof(PktAdmin), CmdCharAdminCmd, 0, PktAdmin::E_LOGOUT_CHAR))
{
lpGameDispatch->GetSendStream().PutBuffer(
reinterpret_cast<char*>(&pktSendAdmin), sizeof(PktAdmin), CmdCharAdminCmd);
}
}
}
}
*/
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktSendAdmin),
sizeof(PktAdmin), CmdCharAdminCmd, 0, 0))
{
// 모든 게임서버로 전송.
GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktSendAdmin), sizeof(PktAdmin), CmdCharAdminCmd));
}
return true;
}
bool CGameDispatch::GiveItemToTempInven(PktBase* lpPktBase)
{
PktGiveItemToTempInven* lpPktGiveItemToTempInven =
static_cast<PktGiveItemToTempInven*>(lpPktBase);
GiveItemInfo* lpPos = lpPktGiveItemToTempInven->m_GiveItemInfo;
GiveItemInfo* lpEnd = lpPos + lpPktGiveItemToTempInven->m_cGiveItemNum;
CGiveItemMgr& giveItemMgr = CGiveItemMgr::GetInstance();
for(; lpPos != lpEnd; ++lpPos)
{
// 아이템 넣기에 성공했으면 아이템 시리얼을 채워서 준다. 채워서 준 시리얼을 DB에 갱신한다.
if(0 != lpPos->m_dwItemUID)
{
giveItemMgr.UpdateItemSerial(
lpPos->m_dwCreateID, lpPos->m_dwItemUID);
}
}
return true;
}
bool CGameDispatch::ChangeName(PktBase* lpPktBase)
{
PktCharNameChange* lpCharNameChange =
reinterpret_cast<PktCharNameChange*>(lpPktBase);
unsigned long dwUID = lpCharNameChange->m_dwUID;
unsigned long dwCID = lpCharNameChange->m_dwCID;
const char* szChangeName = lpCharNameChange->m_szCharName;
Item::ItemPos ItemPos = lpCharNameChange->m_ItemPos; // 계명허가서 위치
unsigned char cNameChangeCount = 0;
unsigned short usError = 0;
using namespace DBAgent::DataStorage;
CSessionData* lpSessionData =
CSessionDataMgr::GetInstance().GetCharLoadedSession(dwCID);
CCharacterData* lpCharacterData = 0;
if (0 != lpSessionData &&
lpSessionData->GetUID() == dwUID &&
lpSessionData->GetCID() == dwCID &&
(0 != (lpCharacterData = lpSessionData->GetCharacterData())) &&
dwCID == lpCharacterData->GetCID())
{
unsigned long dwResult = 0;
const char* szPrevName = lpCharacterData->GetName();
// 카운트를 줄인다.
CHAR_INFOEX infoEx = lpCharacterData->GetInfoEx();
/*
if (0 == infoEx.cNameChangeCount)
{
usError = PktCharNameChange::ERR_NAMECHANGE_COUNT;
}
else
*/
// 이상이 없으면 여기서 아이템을 감소시킨다.
if (DBComponent::GameDB::ChangeCharName(
CDBSingleObject::GetInstance(), dwCID, szChangeName, dwResult))
{
if (0 == dwResult)
{
CHAR_INFOST charInfoST = lpCharacterData->GetInfo();
strncpy(charInfoST.Name, szChangeName, CHAR_INFOST::MAX_NAME_LEN);
charInfoST.Name[CHAR_INFOST::MAX_NAME_LEN - 1] = 0;
lpCharacterData->SetInfo(charInfoST, true);
infoEx.cNameChangeCount = 0;
// --infoEx.cNameChangeCount; // 아이템으로 바뀐후 이부분은 사용안함.
cNameChangeCount = infoEx.cNameChangeCount;
lpCharacterData->SetInfoEx(infoEx);
// 랭킹에서 찾는다 //
if(CRankingMgr::GetInstance().GetRank(szPrevName, (unsigned char)lpCharacterData->GetClass()))
{
const CHAR_INFOST& charInfo = lpCharacterData->GetInfo();
// 데이터 삭제 //
CRankingDBMgr::GetInstance().DeleteRanking(RankingNode(szPrevName, charInfo.Fame,
static_cast<unsigned char>(charInfo.Level), static_cast<unsigned char>(charInfo.Class)));
// 데이터 업데이트 //
CRankingDBMgr::GetInstance().UpdateRanking(RankingNode(szChangeName, charInfo.Fame,
static_cast<unsigned char>(charInfo.Level), static_cast<unsigned char>(charInfo.Class)));
}
}
else if(1 == dwResult)
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / 캐릭터 이름 바꾸기 실패 : 이름이 이미 있습니다",
dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_ALREADY_USE_NAME;
}
else
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / dwResult:%10u / 캐릭터 이름 바꾸기 실패 : 알 수 없는 dwResult값입니다",
dwUID, dwCID, szChangeName, dwResult);
usError = PktCharNameChange::ERR_SERVER;
}
}
else
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / 캐릭터 이름 바꾸기 실패 : DB호출 에러",
dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_SERVER;
}
}
else
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ChangeName:%s / "
"캐릭터 이름 바꾸기 실패 : 캐릭터가 활성화 된 세션이 없습니다",
dwUID, dwCID, szChangeName);
usError = PktCharNameChange::ERR_CANNOT_FIND_CHARACTER;
}
GameClientSendPacket::SendCharNameChange(GetSendStream(), dwUID, dwCID,
szChangeName, cNameChangeCount, &ItemPos, usError);
return true;
}
void CGameDispatch::IncCharNum(int nRace)
{
switch(nRace)
{
case CClass::HUMAN: ++m_nHumanNum; break;
case CClass::AKHAN: ++m_nAkhanNum; break;
}
}
void CGameDispatch::DecCharNum(int nRace)
{
switch(nRace)
{
case CClass::HUMAN: --m_nHumanNum; break;
case CClass::AKHAN: --m_nAkhanNum; break;
}
}
int CGameDispatch::GetCharNum(int nRace) const
{
int nNum = -1;
switch(nRace)
{
case CClass::HUMAN: nNum = m_nHumanNum; break;
case CClass::AKHAN: nNum = m_nAkhanNum; break;
}
return (nNum < 1) ? 1 : nNum;
}
int CGameDispatch::GetCharNum() const
{
int nUserNumber = m_nHumanNum + m_nAkhanNum - 1;
return (nUserNumber < 1) ? 1 : nUserNumber;
}
// 나중에 개수 많아지면 분리할 것..
bool ParseServerLog(CSendStream& SendStream, PktBase* lpPktBase)
{
PktServerLog* lpPktServerLog = static_cast<PktServerLog*>(lpPktBase);
switch(lpPktServerLog->m_cLogCmd)
{
case PktServerLog::ITEM_DUPLICATED_LOG:
{
PktItemDuplicated* lpPktItemDup = static_cast<PktItemDuplicated*>(lpPktServerLog);
if(!DBComponent::GameDB::InsertItemDuplicatedLog(CDBSingleObject::GetInstance(),
lpPktItemDup->m_dwItemSerial, lpPktItemDup->m_szName,
lpPktItemDup->m_dwUID, lpPktItemDup->m_dwCID, lpPktItemDup->m_dwQty))
{
ERRLOG5(g_Log, "UID:%10u / CID:%10u / CharName:%s / ItemSerial:0x%I64X / Qty:%u / 아이템 복사가 발견되었습니다",
lpPktItemDup->m_dwUID, lpPktItemDup->m_dwCID, lpPktItemDup->m_szName,
lpPktItemDup->m_dwItemSerial, lpPktItemDup->m_dwQty);
}
}
break;
}
return true;
}
// -----------------------------------------------------------------------------------
// 각종 함수자 메서드
CGetTotalCount::CGetTotalCount(unsigned short& usHumanCount,
unsigned short& usAkhanCount,
unsigned char& cChannelCount)
: m_usHumanCount(usHumanCount),
m_usAkhanCount(usAkhanCount),
m_cChannelCount(cChannelCount)
{
m_usHumanCount = 0;
m_usAkhanCount = 0;
m_cChannelCount = 0;
}
bool CGetTotalCount::operator () (unsigned long dwServerID, CPacketDispatch& packetDispatch)
{
CGameDispatch& gameDispatch = reinterpret_cast<CGameDispatch&>(packetDispatch);
int nCharNum = gameDispatch.GetCharNum(CClass::HUMAN);
m_usHumanCount += nCharNum;
nCharNum = gameDispatch.GetCharNum(CClass::AKHAN);
m_usAkhanCount += nCharNum;
++m_cChannelCount;
return true;
}
CUserPercentageInZone::CUserPercentageInZone(unsigned short* lpChannelUserNum,
unsigned char cZone, unsigned char cChannelNum)
: m_lpChannelUserNum(lpChannelUserNum),
m_cZone(cZone),
m_cChannelNum(cChannelNum),
m_nMaxUserNum(CServerSetup::GetInstance().GetUserLimit())
{
std::fill_n(m_lpChannelUserNum, m_cChannelNum, 0);
}
bool CUserPercentageInZone::operator () (unsigned long dwServerID, CPacketDispatch& packetDispatch)
{
CGameDispatch& gameDispatch = reinterpret_cast<CGameDispatch&>(packetDispatch);
SERVER_ID serverID;
serverID.dwID = dwServerID;
if(serverID.GetZone() == m_cZone)
{
if(serverID.GetChannel() < m_cChannelNum)
{
m_lpChannelUserNum[serverID.GetChannel()] =
gameDispatch.GetCharNum() * 100 / m_nMaxUserNum + 1;
}
}
return true;
}
CSendPacketToZone::CSendPacketToZone(const char* szData, unsigned long dwDataLen,
unsigned char cPacketCmd, unsigned char cZone)
: m_szData(szData), m_dwDataLen(dwDataLen),
m_cPacketCmd(cPacketCmd), m_cZone(cZone)
{
}
bool CSendPacketToZone::operator () (unsigned long dwServerID, CPacketDispatch& packetDispatch)
{
SERVER_ID serverID;
serverID.dwID = dwServerID;
if(serverID.GetZone() == m_cZone)
{
return reinterpret_cast<CRylServerDispatch&>(packetDispatch).GetSendStream().PutBuffer(
m_szData, m_dwDataLen, m_cPacketCmd);
}
return true;
}
}

View File

@@ -0,0 +1,118 @@
#ifndef _DBAGENT_SERVER_GAME_DISPATCH_H_
#define _DBAGENT_SERVER_GAME_DISPATCH_H_
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <Item/ItemSerialMgr.h>
// forward decl.
struct PktSL;
struct PktBase;
struct PktUK;
struct PktAdmin;
namespace DBAgent
{
class CGameDispatch : public CRylServerDispatch
{
public:
static CMultiDispatch& GetDispatchTable();
enum Const
{
// edith 2008.03.04 CGameDispatch 수정
MAX_PACKET_DISPATCH_PER_PULSE = 100,
MAX_STREAM_BUFFER_SIZE = 16000
};
CGameDispatch(CSession& Session);
virtual ~CGameDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
void IncCharNum(int nRace);
void DecCharNum(int nRace);
int GetCharNum(int nRace) const; // 항상 실 인원수보다 한명이 많다.
int GetCharNum() const; // 항상 실 인원수보다 한명이 많다.
unsigned long GetServerID() const { return m_dwServerID; }
private:
bool ServerLogin(PktBase* lpPktBase);
bool ServerLogout(PktBase* lpPktBase);
bool UserKillAck(PktBase* lpPktBase);
bool CharAdminCmd(PktBase* lpPktBase);
bool GiveItemToTempInven(PktBase* lpPktBase);
bool ChangeName(PktBase* lpPktBase);
Item::CItemSerialMgr m_GameItemSerialMgr;
// 인원수는 항상 한명이 많게 관리하고, 보여줄때만 1씩 빼서 보여준다.
// 그 이유는 채널의 존재 여부를 인원수가 0인지 아닌지로 파악하기 때문이다.
int m_nHumanNum;
int m_nAkhanNum;
unsigned long m_dwServerID;
};
// 전체 캐릭터 수를 얻어오는 함수자이다. CMultiDispatch::Process 에 사용한다.
class CGetTotalCount
{
public:
CGetTotalCount(unsigned short& usHumanCount, unsigned short& usAkhanCount,
unsigned char& cChannelCount);
bool operator () (unsigned long dwServerID, CPacketDispatch& packetDispatch);
private:
unsigned short& m_usHumanCount;
unsigned short& m_usAkhanCount;
unsigned char& m_cChannelCount;
};
// 존당 캐릭터 수 퍼센티지를 얻어오는 함수자이다. CMultiDispatch::Process 에 사용한다.
class CUserPercentageInZone
{
public:
CUserPercentageInZone(unsigned short* lpChannelUserNum,
unsigned char cZone, unsigned char cChannelNum);
bool operator () (unsigned long dwServerID, CPacketDispatch& packetDispatch);
private:
int m_nMaxUserNum;
unsigned short* m_lpChannelUserNum;
unsigned char m_cZone;
unsigned char m_cChannelNum;
};
// 특정 존의 모든 채널에 패킷을 보낸다.
class CSendPacketToZone
{
public:
CSendPacketToZone(const char* szData, unsigned long dwDataLen,
unsigned char cPacketCmd, unsigned char cZone);
bool operator () (unsigned long dwServerID, CPacketDispatch& packetDispatch);
private:
const char* m_szData;
unsigned long m_dwDataLen;
unsigned char m_cPacketCmd;
unsigned char m_cZone;
};
}
#endif

View File

@@ -0,0 +1,64 @@
#include "stdafx.h"
#include "LoginDispatch.h"
#include <Log/ServerLog.h>
#include <Network/Address/INET_Addr.h>
#include <Network/SendPacket/SendServerInfo.h>
#include <Utility/Setup/ServerSetup.h>
namespace DBAgent
{
CSingleDispatch& CLoginDispatch::GetDispatchTable()
{
static CSingleDispatch loginDispatch;
return loginDispatch;
}
CLoginDispatch::CLoginDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE)
{
}
CLoginDispatch::~CLoginDispatch()
{
}
void CLoginDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/LoginServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
GetDispatchTable().SetDispatch(this);
CSendStream& SendStream = GetSendStream();
unsigned long dwServerID = CServerSetup::GetInstance().GetServerID();
SendPacket::ServerLogin(SendStream, dwServerID);
SendPacket::UpdateServerVersion(SendStream);
SendPacket::UpdateChannel(SendStream, dwServerID);
}
void CLoginDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/LoginServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
GetDispatchTable().RemoveDispatch(this);
}
bool CLoginDispatch::DispatchPacket(PktBase* lpPktBase)
{
return true;
}
}

View File

@@ -0,0 +1,34 @@
#ifndef _DBAGENT_SERVER_LOGIN_DISPATCH_H_
#define _DBAGENT_SERVER_LOGIN_DISPATCH_H_
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
namespace DBAgent
{
class CLoginDispatch : public CRylServerDispatch
{
public:
static CSingleDispatch& GetDispatchTable();
enum Const
{
MAX_PACKET_DISPATCH_PER_PULSE = 10,
MAX_STREAM_BUFFER_SIZE = 16000
};
CLoginDispatch(CSession& Session);
virtual ~CLoginDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
private:
};
}
#endif

View File

@@ -0,0 +1,623 @@
#include "stdafx.h"
#include "AuthDispatch.h"
#include "Part1DBAgentDispatch.h"
#include <Log/ServerLog.h>
#include <Network/Address/INET_Addr.h>
#include <Network/SendPacket/SendServerInfo.h>
#include <Network/SendPacket/SendCharManage.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/UnifiedCharPacket.h>
#include <Utility/Setup/ServerSetup.h>
#include <DataStorage/SessionDataMgr.h>
#include <DataStorage/StoreDataMgr.h>
#include <DataStorage/CharacterDataMgr.h>
#include <Creature/Creature.h>
#include <Creature/Character/CharacterClass.h>
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <Network/Packet/PacketStruct/CharQuestPacket.h>
namespace DBAgent
{
class CCharBackupItemData
{
public:
CCharBackupItemData()
: m_bBackupData(false), m_cOldServerGroupID(0)
{
memset(&m_CharInfo, 0, sizeof(CHAR_INFOST)); // 기본 정보
memset(&m_Skill, 0, sizeof(SKILL)); // 스킬 정보
memset(&m_Equip, 0, sizeof(EQUIP)); // 장비
memset(&m_Inven, 0, sizeof(INVEN)); // 인벤
memset(&m_Extra, 0, sizeof(EXTRA)); // 여분
memset(&m_Exchange, 0, sizeof(EXCHANGE)); // 교환
memset(&m_TempInven, 0, sizeof(TEMPINVEN)); // 임시 인벤토리
memset(&m_Quest, 0, sizeof(QUEST)); // 퀘스트
memset(&m_History, 0, sizeof(HISTORY)); // 히스토리
}
bool IsBackupedData() const { return m_bBackupData; }
unsigned char GetOldServerGroupID() const { return m_cOldServerGroupID; }
void BackupData(DataStorage::CSessionData& sessionData, DataStorage::CCharacterData& charData)
{
m_CharInfo = charData.GetInfo();
m_Skill = charData.GetSkill();
m_Equip = charData.GetEquip();
m_Inven = charData.GetInven();
m_Extra = charData.GetExtra();
m_Exchange = charData.GetExchange();
m_TempInven = charData.GetTempInven();
m_Quest = charData.GetQuest();
m_History = charData.GetHistory();
const UnifiedCharData* lpUnifiedCharData =
sessionData.GetUnifiedCharData(charData.GetCID());
if(0 != lpUnifiedCharData)
{
m_cOldServerGroupID = lpUnifiedCharData->cOldServerGroupID;
}
m_bBackupData = true;
}
void RestoreData(DataStorage::CCharacterData& charData)
{
if (m_bBackupData)
{
charData.SetInfo(m_CharInfo);
charData.SetSkill(m_Skill);
charData.SetEquip(m_Equip.Data, m_Equip.dwSize);
charData.SetInven(m_Inven.Data, m_Inven.dwSize);
charData.SetExtra(m_Extra.Data, m_Extra.dwSize);
charData.SetExchange(m_Exchange.Data, m_Exchange.dwSize);
charData.SetTempInven(m_TempInven.Data, m_TempInven.dwSize);
charData.SetQuest(m_Quest);
charData.SetHistory(m_History);
}
}
private:
CHAR_INFOST m_CharInfo; // 기본 정보
SKILL m_Skill; // 스킬 정보
EQUIP m_Equip; // 장비
INVEN m_Inven; // 인벤
EXTRA m_Extra; // 여분
EXCHANGE m_Exchange; // 교환
TEMPINVEN m_TempInven; // 임시 인벤토리
QUEST m_Quest; // 퀘스트
HISTORY m_History; // History
unsigned char m_cOldServerGroupID; // 예전 서버그룹 ID
bool m_bBackupData; // 데이터 백업되었는지 여부
};
void ProcessUnifiedCharSelect(CSendStream& SendStream, PktBase* lpPktBase);
CSingleDispatch& CPart1DBAgentDispatch::GetDispatchTable()
{
static CSingleDispatch part1DBAgentDispatch;
return part1DBAgentDispatch;
}
CPart1DBAgentDispatch::CPart1DBAgentDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE)
{
}
CPart1DBAgentDispatch::~CPart1DBAgentDispatch()
{
}
void CPart1DBAgentDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Part1 DBAgentServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
GetDispatchTable().SetDispatch(this);
SendPacket::ServerLogin(GetSendStream(),
CServerSetup::GetInstance().GetServerID());
}
void CPart1DBAgentDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Part1 DBAgentServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
GetDispatchTable().RemoveDispatch(this);
}
bool CPart1DBAgentDispatch::DispatchPacket(PktBase* lpPktBase)
{
switch(lpPktBase->GetCmd())
{
case CmdUnifiedCharSelect:
ProcessUnifiedCharSelect(GetSendStream(), lpPktBase);
break;
}
return true;
}
bool CPart1DBAgentDispatch::TransferCharPart1ToPart2(CSendStream& SendStream, unsigned long dwUID,
unsigned char cSelectedServerGroup,
unsigned char cSelectedNation,
unsigned long* lpdwSelectedCID,
unsigned char cSelectedCharNum)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktUnifiedCharSelectReq));
if(0 != lpBuffer)
{
PktUnifiedCharSelectReq* lpPktUnifiedCharSelectReq =
reinterpret_cast<PktUnifiedCharSelectReq*>(lpBuffer);
memset(lpPktUnifiedCharSelectReq->szPassword, 0,
sizeof(char) * PktUnifiedCharSelectReq::MAX_PASSWORD_LEN);
lpPktUnifiedCharSelectReq->cSelectedNation = cSelectedNation;
lpPktUnifiedCharSelectReq->cSelectedServerGroupID = cSelectedServerGroup;
lpPktUnifiedCharSelectReq->dwRequestKey = 0;
lpPktUnifiedCharSelectReq->dwUID = dwUID;
memcpy(lpPktUnifiedCharSelectReq->dwCID, lpdwSelectedCID,
sizeof(unsigned long) * std::min(int(cSelectedCharNum), int(USER_INFO::MAX_CHAR_NUM)));
return SendStream.WrapHeader(sizeof(PktUnifiedCharSelectReq), CmdUnifiedCharSelect, 0, 0);
}
return false;
}
void ProcessUnifiedCharSelect(CSendStream& SendStream, PktBase* lpPktBase)
{
PktUnifiedCharSelectReq* lpPktUnifiedCharSelectReq =
reinterpret_cast<PktUnifiedCharSelectReq*>(lpPktBase);
unsigned long dwUID = lpPktUnifiedCharSelectReq->dwUID;
unsigned long dwRequestKey = lpPktUnifiedCharSelectReq->dwRequestKey;
unsigned char cSelectedServerGroupID = lpPktUnifiedCharSelectReq->cSelectedServerGroupID;
unsigned char cSelectedNation = lpPktUnifiedCharSelectReq->cSelectedNation;
unsigned short usError = 0;
using namespace DBAgent::DataStorage;
unsigned char cAgentServerType = static_cast<unsigned char>(
CServerSetup::GetInstance().GetAgentServerType());
CStoreDataMgr& storeDataMgr = CStoreDataMgr::GetInstance();
CCharacterDataMgr& charDataMgr = CCharacterDataMgr::GetInstance();
CDBComponent& dbComponent = CDBSingleObject::GetInstance();
UnifiedStoreKey srcStoreKey(dwUID, cSelectedServerGroupID);
UnifiedStoreKey dstStoreKey(dwUID, cAgentServerType);
CSessionData* lpSessionData = 0;
CStoreData* lpStoreData = 0;
CCharacterData* lpCharacterData = 0;
if(0 != lpPktBase->GetError())
{
// 해당 UID가 없다.
ERRLOG2(g_Log, "UID:%10u / Part2Unified 캐릭터 선택 실패 - Part1 DB중계서버에서 %d에러를 전송했습니다.",
dwUID, lpPktBase->GetError());
usError = lpPktBase->GetError();
}
else if(0 == (lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(dwUID)))
{
// 해당 UID가 없다.
ERRLOG1(g_Log, "UID:%10u / Part2Unified 캐릭터 선택 실패 - 세션이 닫혀 있습니다", dwUID);
usError = PktUnifiedCharSelectAck::SERVER_ERROR;
}
else
{
// 창고 선택한 적 없음
if (!(lpSessionData->GetFirstLogin() & UnifiedConst::SELECTED_PART2))
{
// 혹시 캐쉬나 loginDB에 데이터가 들어있는지 살핀다. 있으면 전부 제거한다.
if(storeDataMgr.IsDataLoginDB(srcStoreKey))
{
ERRLOG2(g_Log, "UID:%10u / SrcServerGroupID:%d / Part2Unified 창고 선택 실패 - 해당 창고가 로그인해 있습니다.",
srcStoreKey.first, srcStoreKey.second);
usError = PktUnifiedCharSelectAck::SERVER_ERROR;
}
else if(storeDataMgr.IsDataLoginDB(dstStoreKey))
{
ERRLOG2(g_Log, "UID:%10u / DstServerGroupID:%d / Part2Unified 창고 선택 실패 - 해당 창고가 로그인해 있습니다.",
dstStoreKey.first, dstStoreKey.second);
usError = PktUnifiedCharSelectAck::SERVER_ERROR;
}
else
{
// 일단 캐쉬에서 데이터를 내린다.
if(storeDataMgr.RemoveLogoutData(srcStoreKey))
{
ERRLOG2(g_Log, "UID:%10u / SrcServerGroupID:%d / "
"Part2Unified 창고 선택 이상 - 해당 데이터가 캐쉬에 들어 있어 강제로 내립니다.",
srcStoreKey.first, srcStoreKey.second);
}
if(storeDataMgr.RemoveLogoutData(dstStoreKey))
{
ERRLOG2(g_Log, "UID:%10u / DstServerGroupID:%d / "
"Part2Unified 창고 선택 이상 - 해당 데이터가 캐쉬에 들어 있어 강제로 내립니다.",
dstStoreKey.first, dstStoreKey.second);
}
// 선택한 서버군 창고를 내 서버그룹 창고로 복사한다!
if (!lpSessionData->ChangeUnifiedStoreInfoGroup(
dbComponent, cSelectedServerGroupID, cAgentServerType))
{
usError = PktUnifiedCharSelectAck::UNIFIED_STORE_READ_ERROR;
}
// 복사 잘 됐으면 캐쉬로 로드해서 컨버팅을 한다.
else
{
if(0 == (lpStoreData = storeDataMgr.GetLogoutData(dstStoreKey)))
{
ERRLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 창고 캐쉬로 데이터 로드 실패",
dwUID, cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_STORE_READ_ERROR;
}
// 창고 데이터를 Part2아이템으로 컨버팅한다.
else if (!lpStoreData->ConvertToPart2Item(true))
{
ERRLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 창고 파트2 아이템으로 아이템 컨버팅 실패",
dwUID, cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_STORE_WRITE_ERROR;
}
// 창고 데이터를 저장한다.
else if(!lpStoreData->ForceUpdateDBAllData(dbComponent))
{
ERRLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 컨버팅된 창고 데이터를 저장 실패",
dwUID, cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_STORE_WRITE_ERROR;
}
else if(!DBComponent::GameDB::UpdateUserFirstLogin(dbComponent, dwUID,
lpSessionData->GetFirstLogin() | UnifiedConst::SELECTED_PART2))
{
ERRLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 창고 가져왔음을 기록 실패",
dwUID, cSelectedServerGroupID);
}
if(0 != usError)
{
// 에러가 난 건 창고 데이터를 저장을 못 했기 때문이니,
// 그냥 캐쉬에서 날리고 다시 세팅하면 된다.
storeDataMgr.RemoveLogoutData(dstStoreKey);
if(!lpSessionData->ChangeUnifiedStoreInfoGroup(
dbComponent, cAgentServerType, cSelectedServerGroupID))
{
ERRLOG3(g_Log, "UID:%10u / ServerGroupID:%d -> %d / 통합서버 선택 실패 : 창고 데이터 롤백 실패",
dwUID, cAgentServerType, cSelectedServerGroupID);
}
}
else
{
lpSessionData->SetFirstLogin(
lpSessionData->GetFirstLogin() | UnifiedConst::SELECTED_PART2);
INFLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 통합서버 선택 성공",
dwUID, cSelectedServerGroupID);
}
}
}
}
// 캐릭터 선택 쪽을 처리한다.
// 1. 캐릭터를 받으면, 일단 UserInfo를 로드한 후에,
// 올바른 슬롯에 넣은 중복되지 않는 캐릭터를 찾는다.
// 2. 정리가 끝나면 Part1 DB중계서버에, 해당 캐릭터를 캐쉬에서 언로드하고
// 길드 / 파티를 탈퇴시키라고 요청한다.
// 3. 요청 결과가 성공으로 돌아오면, 해당 캐릭터를 DB에서 로드하고
// 데이터를 컨버팅 한 후에 저장한다. 컨버팅이나 저장이 실패하면 데이터를 롤백한다.
// 4. 모든 작업이 무사히 끝나면, DB의 UserInfo를 갱신한다.
CClass::RaceType eRace =
lpSessionData->CheckUnifiedCharRace(lpPktUnifiedCharSelectReq->dwCID);
USER_INFO userInfo = lpSessionData->GetUserInfo();
// 유저 바인딩 검사를 한번 더 한다.
unsigned long dwSelectedCID[USER_INFO::MAX_CHAR_NUM];
unsigned long* lpdwRequestedCID = lpPktUnifiedCharSelectReq->dwCID;
int nSelectedCount = 0;
std::fill_n(dwSelectedCID, size_t(USER_INFO::MAX_CHAR_NUM), 0);
// 데이터를 제대로 얻어 왔다.
// 현재 바인딩 된 캐릭터인지 아닌지 판단한다.
unsigned char cRestrictedPart1ToPart2Level =
CServerSetup::GetInstance().GetRestrictedPart1ToPart2Level();
for(int nCount = 0; nCount < USER_INFO::MAX_CHAR_NUM; ++nCount)
{
unsigned long dwBindCID = lpdwRequestedCID[nCount];
const UnifiedCharData* lpUnifiedCharData = 0;
if (0 == userInfo.CharID[nCount] &&
0 != dwBindCID && !userInfo.HasCharacter(dwBindCID) &&
0 != (lpUnifiedCharData = lpSessionData->GetUnifiedCharData(dwBindCID)) &&
(lpUnifiedCharData->cOldServerGroupID < UnifiedConst::Part1 ||
(lpUnifiedCharData->cOldServerGroupID == UnifiedConst::Part1Unified &&
cRestrictedPart1ToPart2Level <= lpUnifiedCharData->cLevel)))
{
dwSelectedCID[nCount] = dwBindCID;
++nSelectedCount;
}
}
if (0 < nSelectedCount && CClass::MAX_RACE == eRace)
{
usError = PktUnifiedCharSelectAck::PACKET_ERROR;
}
else if(0 == usError)
{
// 한바퀴 돌면서 아이템 컨버팅 / 스킬북 컨버팅 등을 수행한다.
CCharBackupItemData backupData[USER_INFO::MAX_CHAR_NUM];
for(int nCount = 0; nCount < USER_INFO::MAX_CHAR_NUM; ++nCount)
{
if(0 != dwSelectedCID[nCount])
{
if(0 == (lpCharacterData = charDataMgr.GetLogoutData(dwSelectedCID[nCount])))
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 캐릭터 캐쉬로 데이터 로드 실패",
dwUID, dwSelectedCID[nCount], cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_CHAR_READ_ERROR;
}
else
{
// 데이터를 백업한다.
backupData[nCount].BackupData(*lpSessionData, *lpCharacterData);
// Part2 아이템으로 컨버팅한다.
if (!lpCharacterData->ConvertToPart2Item(true))
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 캐릭터 Part2아이템으로 컨버팅 실패",
dwUID, dwSelectedCID[nCount], cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_CHAR_WRITE_ERROR;
}
// UnifiedCharInfo에서, 캐릭터 서버군 번호를 수정한다.
else if (!lpSessionData->ChangeUnifiedCharServerGroupID(
dbComponent, dwUID, dwSelectedCID[nCount], cAgentServerType))
{
usError = PktUnifiedCharSelectAck::UNIFIED_CHAR_WRITE_ERROR;
}
else if (!lpCharacterData->ForceUpdateDBAllData(dbComponent))
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 캐릭터 아이템 저장 실패",
dwUID, dwSelectedCID[nCount], cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_CHAR_WRITE_ERROR;
}
if(0 != usError)
{
// 에러가 있으면 바로 롤백;;
break;
}
// 양국체제로 변경 //
if(lpSessionData->GetAccountNation()==Creature::ALMIGHTY_PIRATE)
{
/* 국적이 신의 해적단이면서, 종족이 휴먼인 사람들의 국적을 카르테란트로 바꿔준다. */
if(lpCharacterData->GetRace()==CClass::HUMAN)
{
lpSessionData->SetAccountNation(Creature::KARTERANT);
}
/* 국적이 신의 해적단이면서, 종족이 아칸인 사람들의 국적을 메르카디아로 바꿔준다. */
else if(lpCharacterData->GetRace()==CClass::AKHAN)
{
lpSessionData->SetAccountNation(Creature::MERKADIA);
}
}
// 친구리스트, 거부 리스트 삭제 //
/*unsigned long dwMemberCID[CFriendList::MAX_FRIENDS_NUM] = {0,};
unsigned long dwDeleteCID[CFriendList::MAX_FRIENDS_NUM] = {0,};
// 친구리스트에 CID 만 가지고 온다. //
CFriendList friendList = lpCharacterData->GetFriendList();
friendList.GetCIDList(dwMemberCID);
for(unsigned char cIndex = 0; cIndex < friendList.GetFriendNum(); cIndex++)
{
CFriendList::Rebind* lpRebind = friendList.GetFriend(dwMemberCID[cIndex]);
if(lpCharacterData->GetRace()==CClass::HUMAN)
{
if(lpRebind->GetClass()>=CClass::Combatant)
{
dwDeleteCID[cIndex] = dwMemberCID[cIndex];
}
}
else if(lpCharacterData->GetRace()==CClass::AKHAN)
{
if(lpRebind->GetClass()<CClass::Combatant)
{
dwDeleteCID[cIndex] = dwMemberCID[cIndex];
}
}
// 다른 종족일 경우 삭제 //
if(dwDeleteCID[cIndex])
{
friendList.Remove(dwDeleteCID[cIndex]);
}
}
memset(dwMemberCID, 0, sizeof(unsigned long) * CFriendList::MAX_FRIENDS_NUM);
memset(dwDeleteCID, 0, sizeof(unsigned long) * CFriendList::MAX_FRIENDS_NUM);
CBanList banList = lpCharacterData->GetBanList();
banList.GetCIDList(dwMemberCID);
for(unsigned char cIndex = 0; cIndex < banList.GetBanNum(); cIndex++)
{
CBanList::Rebind* lpRebind = banList.GetBan(dwMemberCID[cIndex]);
if(lpCharacterData->GetRace()==CClass::HUMAN)
{
if(lpRebind->GetClass()>=CClass::Combatant)
{
dwDeleteCID[cIndex] = dwMemberCID[cIndex];
}
}
else if(lpCharacterData->GetRace()==CClass::AKHAN)
{
if(lpRebind->GetClass()<CClass::Combatant)
{
dwDeleteCID[cIndex] = dwMemberCID[cIndex];
}
}
// 다른 종족일 경우 삭제 //
if(dwDeleteCID[cIndex])
{
banList.Remove(dwDeleteCID[cIndex]);
}
}*/
}
}
}
// 에러가 없으면 데이터를 바인딩한다.
if(0 == usError)
{
// 선택된 캐릭터가 한마리도 없었으면, 국적을 선택한다.
if(0 == userInfo.GetCharacterNum())
{
unsigned char cOldAccountNation = lpSessionData->GetAccountNation();
// 선택한 국가가 종족과 맞는지 체크한 후 세팅한다.
if(Creature::ALMIGHTY_PIRATE == cSelectedNation)
{
lpSessionData->SetAccountNation(Creature::ALMIGHTY_PIRATE);
}
else
{
lpSessionData->SetAccountNation(
CClass::HUMAN == eRace ? Creature::KARTERANT : Creature::MERKADIA);
}
if (cOldAccountNation != lpSessionData->GetAccountNation())
{
INFLOG3(g_Log, "UID:%10u / OldAccountNation:%s / AccountNation:%s / 국적 변경",
dwUID, Creature::GetShortNationName(cOldAccountNation),
Creature::GetShortNationName(lpSessionData->GetAccountNation()));
}
}
if(!lpSessionData->UpdateCharacterBinding(dbComponent, dwSelectedCID))
{
ERRLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 통합서버 선택 실패 : 최종 캐릭터 바인딩에 실패했습니다",
dwUID, cSelectedServerGroupID);
usError = PktUnifiedCharSelectAck::UNIFIED_CHAR_WRITE_ERROR;
}
else
{
// 창고/캐릭터 이전에 성공했다!
lpSessionData->SetOldServerGroupID(cAgentServerType);
}
}
if(0 != usError)
{
// 문제가 생겼다. 데이터를 전부 Rollback한다.
for(int nCount = 0; nCount < USER_INFO::MAX_CHAR_NUM; ++nCount)
{
if(0 != dwSelectedCID[nCount] && backupData[nCount].IsBackupedData())
{
if(0 == (lpCharacterData = charDataMgr.GetLogoutData(dwSelectedCID[nCount])))
{
ERRLOG3(g_Log, "UID:%10u / CID:%10u / ServerGroupID:%d / 통합서버 선택 실패 - 데이터 복구 실패 : 캐릭터 캐쉬로 데이터 로드 실패",
dwUID, dwSelectedCID[nCount], cSelectedServerGroupID);
}
else
{
backupData[nCount].RestoreData(*lpCharacterData);
lpCharacterData->ForceUpdateDBAllData(dbComponent);
lpSessionData->ChangeUnifiedCharServerGroupID(dbComponent,
dwUID, dwSelectedCID[nCount], backupData[nCount].GetOldServerGroupID());
}
}
}
}
}
}
GET_SINGLE_DISPATCH(lpAuthDispatch, CAuthDispatch,
CAuthDispatch::GetDispatchTable());
if(0 != lpAuthDispatch && SendPacket::UnifiedCharSelectAck(
lpAuthDispatch->GetSendStream(), dwUID, dwRequestKey, usError))
{
if(0 == usError)
{
INFLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 캐릭터 및 창고 선택 성공",
dwUID, cSelectedServerGroupID);
}
}
else
{
ERRLOG2(g_Log, "UID:%10u / ServerGroupID:%d / 캐릭터 선택 실패 : "
"인증서버와 접속이 끊기거나 전송에 실패했습니다.", dwUID, cSelectedServerGroupID);
}
}
}

View File

@@ -0,0 +1,44 @@
#ifndef _DBAGENT_SERVER_PART1_DBAGENT_DISPATCH_H_
#define _DBAGENT_SERVER_PART1_DBAGENT_DISPATCH_H_
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Community/FriendList.h>
#include <Community/BanList.h>
namespace DBAgent
{
// Part1 DBAgent¼­¹ö¿¡ Á¢¼ÓÇÑ´Ù.
class CPart1DBAgentDispatch : public CRylServerDispatch
{
public:
static CSingleDispatch& GetDispatchTable();
enum Const
{
MAX_PACKET_DISPATCH_PER_PULSE = 100,
MAX_STREAM_BUFFER_SIZE = 16000
};
CPart1DBAgentDispatch(CSession& Session);
virtual ~CPart1DBAgentDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
static bool TransferCharPart1ToPart2(CSendStream& SendStream, unsigned long dwUID,
unsigned char cSelectedServerGroup, unsigned char cSelectedNation,
unsigned long* lpdwSelectedCID, unsigned char cSelectedCharNum);
private:
};
typedef std::map<unsigned short, unsigned short> QuestDelete;
typedef std::map<unsigned short, unsigned short> QuestChange;
}
#endif

View File

@@ -0,0 +1,731 @@
#include "stdafx.h"
#include "UIDDispatch.h"
#include "AuthDispatch.h"
#include "GameDispatch.h"
#include "ChatDispatch.h"
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <Log/ServerLog.h>
#include <Network/Address/INET_Addr.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Packet/PacketStruct/CharLoginOutPacket.h>
#include <Network/Packet/PacketStruct/CharLoginOutPacketStruct.h>
#include <Network/SendPacket/SendServerInfo.h>
#include <Network/SendPacket/SendLoginout.h>
#include <Network/SendPacket/SendCharManage.h>
#include <DataStorage/Billing.h>
#include <DataStorage/SessionData.h>
#include <DataStorage/SessionDataMgr.h>
#include <Utility/Setup/ServerSetup.h>
namespace DBAgent
{
const char* g_szPktUUTString[PktUUT::MAX_UPDATE_TYPE] =
{
"UpdateUIDTableNone",
"UpdateUIDTableUserLogin",
"UpdateUIDTableUserLogout",
"UpdateUIDTableUserMove",
"UpdateUIDTableCharLogin",
"UpdateUIDTableCharLogout",
"UpdateUIDTableCharMove",
"UpdateUIDTableBillingCheck",
};
// UpdateUIDTable처리시 유저 로그인 처리를 한다.
// 리턴값은 상수 에러 문자열이다. NULL이면 성공이다.
const char* ProcessUpdateTableUserLogin(DataStorage::CSessionData& sessionData,
DataStorage::RequestData& requestData,
unsigned long dwFlag, int nPlayTime,
unsigned long dwCRMIndex1,
unsigned char cCmd, char cBillingType,
unsigned short usUUKAckError);
// UpdateUIDTable처리시 캐릭터 로그인 처리를 한다.
// 리턴값은 상수 에러 문자열이다. NULL이면 성공이다.
const char* ProcessUpdateTableCharLogin(DataStorage::CSessionData& sessionData,
DataStorage::RequestData& requestData,
unsigned long dwFlag, int nPlayTime,
unsigned long dwCRMIndex1,
unsigned char cCmd, char cBillingType);
CSingleDispatch& CUIDDispatch::GetDispatchTable()
{
static CSingleDispatch uidDispatch;
return uidDispatch;
}
CUIDDispatch::CUIDDispatch(CSession& Session)
: CRylServerDispatch(Session, MAX_PACKET_DISPATCH_PER_PULSE)
{
}
CUIDDispatch::~CUIDDispatch()
{
}
void CUIDDispatch::Connected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/UIDServer Connected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
GetDispatchTable().SetDispatch(this);
SendPacket::ServerLogin(GetSendStream(),
CServerSetup::GetInstance().GetServerID());
}
void CUIDDispatch::Disconnected()
{
DETLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/UIDServer Disconnected",
&GetSession(), this, GetRemoteAddr().get_addr_string());
GetDispatchTable().RemoveDispatch(this);
}
bool CUIDDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::CMDType cCmd = lpPktBase->GetCmd();
bool bResult = false;
switch(cCmd)
{
case CmdSysServerLogout: bResult = ParseServerLogoutAck(lpPktBase); break;
case CmdUserKill: bResult = ParseUserKill(static_cast<PktUK*>(lpPktBase)); break;
case CmdBillingTimeoutNotify: bResult = ParseBillingTimeNotify(static_cast<PktBTN*>(lpPktBase)); break;
case CmdBillingTimeCheckNotify: bResult = ParseBillingTimeCheckNotify(static_cast<PktBTN*>(lpPktBase)); break;
case CmdHanBTNWarning: bResult = ParseHanBTNWarning(static_cast<PktHanBTN*>(lpPktBase)); break;
case CmdHanBTNUserKill: bResult = ParseHanBTNUserKill(static_cast<PktHanUserKill*>(lpPktBase)); break;
case CmdUpdateUIDTable: bResult = ParseUpdateUIDTable(static_cast<PktUUTAck*>(lpPktBase)); break;
default:
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ UID서버 패킷 처리 실패 : 없는 커맨드입니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
bResult = true;
break;
}
if(!bResult)
{
ERRLOG4(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ UID서버 패킷 처리 실패 : 처리를 실패했습니다",
&GetSession(), this, GetRemoteAddr().get_addr_string(), cCmd);
}
return true;
}
bool CUIDDispatch::ParseServerLogoutAck(PktBase* lpPktBase)
{
INFLOG3(g_Log, "SS:0x%08x/DP:0x%08x/IP:%15s/Cmd:0x%02X/ UID서버 접속 종료 : 서버 로그아웃 패킷을 받았습니다.",
&GetSession(), this, GetRemoteAddr().get_addr_string());
CloseSession();
return true;
}
bool CUIDDispatch::ParseUpdateUIDTable(PktUUTAck* lpPktUUTAck)
{
// edith 2008.01.15 UID에서 보낸 UpdateUIDTable 결과값 처리루틴
using namespace DBAgent::DataStorage;
unsigned char cCmd = lpPktUUTAck->m_cCmd;
unsigned long dwUID = lpPktUUTAck->m_dwUserID;
unsigned long dwFlag = lpPktUUTAck->m_dwFlag;
int nPlayTime = lpPktUUTAck->m_nPlayTime;
unsigned long dwCRMIndex1 = lpPktUUTAck->m_dwCRMIndex1; // 피시방 ID (0이면 개인유저)
char cBillingType = lpPktUUTAck->m_cstrBillingType;
CBilling::WarningType eOldWarnMsgType = CBilling::WARN_BEFORE_1SEC;
CBilling::WarningType eNewWarnMsgType = static_cast<CBilling::WarningType>(lpPktUUTAck->GetState());
const char* szErrorReason = 0;
RequestData requestData;
memset(&requestData, 0, sizeof(RequestData));
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(dwUID);
if(PktUUT::MAX_UPDATE_TYPE <= cCmd)
{
szErrorReason = "로그인 실패 - 알 수 없는 커맨드입니다";
}
else if(0 == lpSessionData)
{
szErrorReason = "로그인 실패 - 세션이 없습니다";
}
else
{
switch(cCmd)
{
case PktUUT::UpdateUIDTableUserLogin:
requestData = lpSessionData->PopRequest();
if(0 == requestData.m_dwRequestKey)
{
szErrorReason = "로그인 실패 - RequestKey가 이상합니다";
}
else
{
szErrorReason = ProcessUpdateTableUserLogin(*lpSessionData, requestData, dwFlag,
nPlayTime, dwCRMIndex1, cCmd, cBillingType, lpPktUUTAck->GetError());
eOldWarnMsgType = lpSessionData->GetBilling().GetWarnMsgType();
lpSessionData->GetBilling().SetWarnMsgType(eNewWarnMsgType);
if(CBilling::WARN_EVERY_MINUTE == eNewWarnMsgType)
{
// 경고 상태로 이행. 매분마다 메시지를 보내도록 한다.
SendPacket::BillingCheckNotify(*lpSessionData, 5, cBillingType);
}
}
break;
case PktUUT::UpdateUIDTableCharLogin:
requestData = lpSessionData->PopRequest();
if(0 == requestData.m_dwRequestKey)
{
szErrorReason = "로그인 실패 - RequestKey가 이상합니다";
}
else
{
szErrorReason = ProcessUpdateTableCharLogin(*lpSessionData, requestData,
dwFlag, nPlayTime, dwCRMIndex1, cCmd, cBillingType);
}
break;
case PktUUT::UpdateUIDTableBillingCheck:
eOldWarnMsgType = lpSessionData->GetBilling().GetWarnMsgType();
if(0 == dwFlag)
{
lpSessionData->GetBilling().SetWarnMsgType(eNewWarnMsgType);
if (CBilling::NO_WARNING == eOldWarnMsgType &&
CBilling::WARN_EVERY_MINUTE == eNewWarnMsgType)
{
// 무경고 상태에서 경고 상태로 이행. 매분마다 메시지를 보내도록 한다.
SendPacket::BillingCheckNotify(*lpSessionData, 5, cBillingType);
}
else
if (CBilling::WARN_EVERY_MINUTE == eOldWarnMsgType &&
CBilling::NO_WARNING == eNewWarnMsgType)
{
// 경고 상태에서 무경고 상태로 이행. 메시지를 그만 보내도록 한다.
SendPacket::BillingCheckNotify(*lpSessionData, 20, cBillingType);
}
}
lpSessionData->GetBilling().AddYouxiLandPoint(nPlayTime, cBillingType);
DETLOG4(g_Log, "UID:%10u / CID:%10u / nPlayTime:%d / cBillingType:%c / UpdateUIDTableBillingCheck 성공",
lpSessionData->GetUID(), lpSessionData->GetCID(), nPlayTime, cBillingType);
if (0 != dwFlag)
{
// 유저 킬 처리 - 특별히 하지 않는다. 나중에 빌링체크에서 끊을 것이다.
// KillUser(lpDataSession);
}
break;
}
}
if(0 != szErrorReason)
{
ERRLOG10(g_Log, "UID:%10u / Cmd:%s / Flag:%u / PlayTime:%d / CRMIndex:%u / BillingType:%c / "
" RequestKey:%10u / SelectedCID:%10u / ServerID:0x%08X / ParseUIDTable 실패 : %s",
dwUID, g_szPktUUTString[cCmd], dwFlag, nPlayTime, dwCRMIndex1, cBillingType,
requestData.m_dwRequestKey, requestData.m_dwSelectedCID,
requestData.m_dwServerID, szErrorReason);
if(0 == dwFlag)
{
PktUUT::UpdateType eUpdateType = PktUUT::UpdateUIDTableNone;
switch(cCmd)
{
case PktUUT::UpdateUIDTableUserLogin:
eUpdateType = PktUUT::UpdateUIDTableUserLogout;
break;
case PktUUT::UpdateUIDTableCharLogin:
eUpdateType = PktUUT::UpdateUIDTableCharLogout;
break;
}
// edith 2008.01.15 UID로 로그인 메시지 전송
if(0 == lpSessionData)
{
ERRLOG1(g_Log, "UID:%10u / UID서버 전송 실패 : 세션이 없습니다.", dwUID);
}
else if(eUpdateType != PktUUT::UpdateUIDTableNone &&
!SendPacket::UpdateUIDTable(eUpdateType, requestData.m_szAccount, requestData.m_szPassword,
dwUID, requestData.m_dwSelectedCID, requestData.m_dwSessionID,
requestData.m_dwServerID, requestData.m_PeerAddress))
{
ERRLOG1(g_Log, "UID:%10u / UID서버 전송 실패 : 전송에 실패했습니다.", dwUID);
}
}
}
return true;
}
const char* ProcessUpdateTableUserLogin(DataStorage::CSessionData& sessionData,
DataStorage::RequestData& requestData,
unsigned long dwFlag, int nPlayTime, unsigned long dwCRMIndex1,
unsigned char cCmd, char cBillingType, unsigned short usUUKAckError)
{
// edith 2008.01.15 UpdateTableUserLogin에 관련된 프로세싱 로직
const char* szErrorReason = 0;
unsigned long dwUID = sessionData.GetUID();
GET_SINGLE_DISPATCH(lpAuthDispatch,
CAuthDispatch, CAuthDispatch::GetDispatchTable());
if(0 == lpAuthDispatch)
{
szErrorReason = "유저 로그인 실패 - 인증서버 접속 끊김";
}
else
{
unsigned short usError = 1; // Default : Server Error(Unknown Error)
if (0 == dwFlag)
{
// 통합서버 정보를 얻어서 보내준다.
unsigned char cAgentServerType = static_cast<unsigned char>(
CServerSetup::GetInstance().GetAgentServerType());
unsigned char cFirstLogin = 0;
switch(cAgentServerType)
{
case UnifiedConst::Part1:
case UnifiedConst::Part1Unified:
// 서버 세팅 잘못 했음. 나중에 UserLogin
szErrorReason = "유저 로그인 실패 - 서버 잘못 켰음";
break;
case UnifiedConst::ROW:
sessionData.SetOldServerGroupID(UnifiedConst::ROW);
break;
case UnifiedConst::Part2Unified:
case UnifiedConst::Part2Selectable:
if(!sessionData.GetUnifiedDataFromDB(CDBSingleObject::GetInstance()))
{
szErrorReason = "유저 로그인 실패 - 통합서버 데이터 얻기 실패";
}
break;
}
cFirstLogin = sessionData.GetFirstLogin();
if(0 != szErrorReason)
{
// 데이터 읽어오다 에러 난 모양이다. UserLogin을 취소한다.
}
else if(!sessionData.UserEnable(CDBSingleObject::GetInstance(), dwUID))
{
szErrorReason = "유저 로그인 실패 - 유저 활성화 실패";
}
else if(!SendPacket::StartSession(lpAuthDispatch->GetSendStream(),
requestData.m_dwRequestKey, dwUID, requestData.m_dwSessionID, cFirstLogin, 0))
{
szErrorReason = "유저 로그인 실패 - 유저 로그인 성공 전송 실패";
}
else
{
// 빌링 시작(접속 끊기 시작. 예전 한게임 과금과 요시랜드 과금만 사용함).
// 인증서버에서는 과금 안함. 과금 정보 표시를 위해서 세팅함.
sessionData.GetBilling().StartBilling(nPlayTime, dwCRMIndex1, cBillingType);
// edith 2008.01.15 로그인에 성공했으니 세션에 등록한다.
// 로그인 성공했을때만 세션 ID등의 데이터를 세팅한다.
sessionData.SetRequestData(requestData);
// 세션 열기 성공
usError = 0;
// StartSession을 받았을 때, 에러가 0이고, 중계서버 타입이 통합서버이면,
// 통합서버 데이터를 기다리므로, 데이터를 여기서 전송해 준다.
switch(cAgentServerType)
{
case UnifiedConst::Part2Unified:
case UnifiedConst::Part2Selectable:
// 신규 계정인지 아닌지 생각할 필요는 없다. 일단 정보 주고 나면
// 선택할 캐릭이 없으면 알아서 그냥 로그인하기 때문이다.
if (!SendPacket::UnifiedCharInfo(lpAuthDispatch->GetSendStream(),
dwUID, sessionData.GetTransferedCharCount(CDBSingleObject::GetInstance()),
sessionData.GetUserInfo(),
sessionData.GetUnifiedStoreInfo(), sessionData.GetUnifiedStoreInfoNum(),
sessionData.GetUnifiedCharData(), sessionData.GetUnifiedCharDataNum()))
{
// 정보 전송에 실패했으면 뭐 하는 수 없지;; 알아서 데이터 기다리다 끊어지겠지;;
ERRLOG1(g_Log, "UID:%10u / 유저 로그인 실패 - 통합서버 정보 전송 실패", dwUID);
}
break;
}
}
}
else if (1 == dwFlag)
{
switch(usUUKAckError)
{
default:
usError = 41; // 중복로그인
break;
case PktUUT::DISCONNECT_USER:
usError = 42; // Disconnect를 했으니 재시도해 봐..
break;
}
}
else if (2 == dwFlag) { usError = 24; } // 개인,피시방 관련 과금 정보가 없음(한게임)
else if (4 == dwFlag) { usError = 1; } // 서버 에러 (DB Query 실패)
else if (11 == dwFlag || 13 == dwFlag || 19 == dwFlag)
{
// 개인,피시방 관련 과금 정보가 없음(대만)
usError = 24;
}
else if (20 == dwFlag) { usError = 40; } // 대만, 일본 중복 로그인 방지
// edith 2009.09.11 MY를 위한 AllowIP 처리작업
else if (57 == dwFlag) { usError = 57; } // ROW에서 AllowIP 에서 걸림
else if (100 >= dwFlag) { usError = (unsigned short)(dwFlag-100); }; // 감마니아 오류
if(0 != usError)
{
SendPacket::StartSession(lpAuthDispatch->GetSendStream(),
requestData.m_dwRequestKey, dwUID, sessionData.GetSessionID(), 0, usError);
}
}
return szErrorReason;
}
const char* ProcessUpdateTableCharLogin(DataStorage::CSessionData& sessionData,
DataStorage::RequestData& requestData,
unsigned long dwFlag, int nPlayTime,
unsigned long dwCRMIndex1,
unsigned char cCmd, char cBillingType)
{
const char* szErrorReason = 0;
unsigned long dwUID = sessionData.GetUID();
GET_MULTI_DISPATCH(lpGameDispatch, requestData.m_dwServerID,
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 == lpGameDispatch)
{
szErrorReason = "캐릭터 로그인 실패 - 게임서버 접속 끊김";
}
else if(!sessionData.HasCharacter(requestData.m_dwSelectedCID))
{
szErrorReason = "캐릭터 로그인 실패 - 소유하지 않은 캐릭터 활성화";
const USER_INFO& userInfo = sessionData.GetUserInfo();
// WORK_LIST 2.1 계정 국적 추가
SERLOG9(g_Log, "UID:%10u / SelectedCID:%10u / Char1:%10u / Char2:%10u / Char3:%10u / Char4:%10u / Char5:%10u / Nation:%d %s",
dwUID, requestData.m_dwSelectedCID,
userInfo.CharID[0], userInfo.CharID[1], userInfo.CharID[2],
userInfo.CharID[3], userInfo.CharID[4], userInfo.Nation, szErrorReason);
}
else
{
// 기본값은 실패. 서버 에러.
unsigned short usError = 1;
if (0 == dwFlag)
{
// 캐릭터 활성화
if (!sessionData.CharEnable(requestData.m_dwSelectedCID, requestData.m_dwServerID))
{
szErrorReason = "캐릭터 로그인 실패 - 세션 활성화 실패";
}
// 캐릭터 데이터 전송
else if (!SendPacket::CharLogin(lpGameDispatch->GetSendStream(),
sessionData, requestData.m_dwRequestKey))
{
szErrorReason = "캐릭터 로그인 실패 - 캐릭터 데이터 전송 실패";
// 활성화된 캐릭터를 Disable함.
sessionData.CharDisable(requestData.m_dwSelectedCID, requestData.m_dwServerID);
}
else
{
// 빌링 시작
switch(CServerSetup::GetInstance().GetBillingType())
{
case CServerSetup::GamaBilling:
case CServerSetup::GamaUnitedBilling:
sessionData.GetBilling().StartBilling(nPlayTime, dwCRMIndex1, cBillingType);
break;
}
// 로그인 성공했을때만 세션 ID등의 데이터를 세팅한다.
sessionData.SetRequestData(requestData);
// 접속 성공!
usError = 0;
}
}
else if (1 == dwFlag) { usError = 41; } // 중복로그인
else if (2 == dwFlag) { usError = 24; } // 개인,피시방 관련 과금 정보가 없음
else if (4 == dwFlag) { usError = 1; } // 서버 에러 (DB Query 실패)
else if (11 == dwFlag || 13 == dwFlag || 19 == dwFlag)
{
// 개인,피시방 관련 과금 정보가 없음(대만)
usError = 24;
}
else if (20 == dwFlag) { usError = 40; } // 대만, 일본 중복 로그인 방지
// edith 2009.09.11 MY를 위한 AllowIP 처리작업
else if (57 == dwFlag) { usError = 57; } // ROW에서 AllowIP 에서 걸림
else if (100 >= dwFlag) { usError = (unsigned short)(dwFlag-100); }; // 감마니아 오류
if (0 != usError)
{
SendPacket::CharLoginError(lpGameDispatch->GetSendStream(),
requestData.m_dwRequestKey, DBUpdateData::LOGIN,
dwUID, requestData.m_dwSelectedCID, usError);
}
}
return szErrorReason;
}
bool CUIDDispatch::ParseBillingTimeNotify(PktBTN* lpPktBTN)
{
using namespace DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(lpPktBTN->m_dwUserID);
if(0 == lpSessionData)
{
ERRLOG2(g_Log, "UID:%10u / cRemainMin:%u / 시간 만료 공지를 보내기 실패 : 유저가 없습니다",
lpPktBTN->m_dwUserID, lpPktBTN->m_cRemainMinute);
}
else if(CSessionData::SE_CHAR_ENABLED != lpSessionData->GetSessionState())
{
ERRLOG2(g_Log, "UID:%10u / ST:%s / 시간 만료 공지를 보내기 실패 : 캐릭터가 비활성화되어 있습니다",
lpPktBTN->m_dwUserID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
else
{
// 시간이 다 떨어져서 경고 보냄.
if(!SendPacket::BillingNotify(*lpSessionData,
lpPktBTN->m_cRemainMinute, lpPktBTN->m_cBillingType))
{
INFLOG4(g_Log, "UID:%10u / ServerID:0x%08X / cRemainMin:%u / cBillingType:%c / 시간 만료 공지 보내기 성공",
lpPktBTN->m_dwUserID, lpSessionData->GetServerID(), lpPktBTN->m_cRemainMinute, lpPktBTN->m_cBillingType);
}
else
{
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 시간 만료 공지를 보내기 실패 : 게임서버와의 연결이 끊어져 있습니다",
lpPktBTN->m_dwUserID, lpSessionData->GetServerID());
}
}
return true;
}
bool CUIDDispatch::ParseBillingTimeCheckNotify(PktBTN* lpPktBTN)
{
using namespace DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(lpPktBTN->m_dwUserID);
if(0 == lpSessionData)
{
ERRLOG2(g_Log, "UID:%10u / cRemainMin:%u / 시간 다시 체크(대만) 공지를 보내기 실패 : 유저가 없습니다",
lpPktBTN->m_dwUserID, lpPktBTN->m_cRemainMinute);
}
else if(CSessionData::SE_CHAR_ENABLED != lpSessionData->GetSessionState())
{
ERRLOG2(g_Log, "UID:%10u / ST:%s / 시간 다시 체크(대만) 공지를 보내기 실패 : 캐릭터가 비활성화되어 있습니다",
lpPktBTN->m_dwUserID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
else
{
// 시간이 다 떨어져서 경고 보냄.
if(!SendPacket::BillingCheckNotify(*lpSessionData,
lpPktBTN->m_cRemainMinute, lpPktBTN->m_cBillingType))
{
INFLOG4(g_Log, "UID:%10u / ServerID:0x%08X / cRemainMin:%u / cBillingType:%c / 시간 다시 체크(대만) 공지 보내기 성공",
lpPktBTN->m_dwUserID, lpSessionData->GetServerID(), lpPktBTN->m_cRemainMinute, lpPktBTN->m_cBillingType);
}
else
{
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 시간 다시 체크 공지(대만)를 보내기 실패 : 게임서버와의 연결이 끊어져 있습니다",
lpPktBTN->m_dwUserID, lpSessionData->GetServerID());
}
}
return true;
}
bool CUIDDispatch::ParseHanBTNWarning(PktHanBTN* lpPktHanBTN)
{
// 채팅서버로 메시지를 Relay한다.
using namespace DataStorage;
IN_ADDR peerAddress;
peerAddress.S_un.S_addr = lpPktHanBTN->m_dwIP;
bool bCheckAddress = (0xFFFFFFFF != peerAddress.S_un.S_addr);
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(
lpPktHanBTN->m_szAccount, peerAddress, bCheckAddress);
if(0 == lpSessionData)
{
ERRLOG2(g_Log, "AccountName:%16s / IP:%15s / 과금 만료 메시지 전송 실패 : 유저가 없습니다",
lpPktHanBTN->m_szAccount, inet_ntoa(peerAddress));
}
else if(CSessionData::SE_CHAR_ENABLED != lpSessionData->GetSessionState())
{
ERRLOG4(g_Log, "UID:%10u / AccountName:%16s / IP:%15s / ST:%s / 과금 만료 메시지 전송 실패 : 캐릭터가 비활성화되어 있습니다",
lpSessionData->GetUID(), lpPktHanBTN->m_szAccount, inet_ntoa(peerAddress),
g_szSessionStateString[lpSessionData->GetSessionState()]);
}
else
{
GET_SINGLE_DISPATCH(lpChatDispatch,
CChatDispatch, CChatDispatch::GetDispatchTable());
if(0 != lpChatDispatch)
{
char* lpBuffer = lpChatDispatch->GetSendStream().GetBuffer(sizeof(PktHanBTN));
if(0 != lpBuffer)
{
PktHanBTN* lpPktChatBTN = reinterpret_cast<PktHanBTN*>(lpBuffer);
*lpPktChatBTN = *lpPktHanBTN;
lpPktChatBTN->m_dwUID = lpSessionData->GetUID();
lpPktChatBTN->m_dwCID = lpSessionData->GetCID();
return lpChatDispatch->GetSendStream().WrapHeader(
sizeof(PktHanBTN), CmdHanBTNWarning, 0, 0);
}
}
ERRLOG5(g_Log, "UID:%10u / AccountName:%16s / IP:%15s / ST:%s / ChatDispatch:%p / 과금 만료 메시지 전송 실패 : 채팅서버와 연결이 끊겼거나, 버퍼 할당 실패",
lpSessionData->GetUID(), lpPktHanBTN->m_szAccount, inet_ntoa(peerAddress),
g_szSessionStateString[lpSessionData->GetSessionState()], lpChatDispatch);
}
return true;
}
bool CUIDDispatch::ParseHanBTNUserKill(PktHanUserKill* lpPktHanUserKill)
{
using namespace DataStorage;
IN_ADDR peerAddress;
peerAddress.S_un.S_addr = lpPktHanUserKill->m_dwIP;
// 접속 DB를 전부 뒤져서, 계정과 IP가 일치하는 넘한테 뜨거운 맛을 보여 준다.
bool bCheckAddress = (peerAddress.S_un.S_addr != 0xFFFFFFFF);
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(
lpPktHanUserKill->m_szAccount, peerAddress, bCheckAddress);
if(0 == lpSessionData)
{
ERRLOG2(g_Log, "AccountName:%16s / IP:%15s / 과금 만료 접속 끊기 실패 : 유저가 없습니다",
lpPktHanUserKill->m_szAccount, inet_ntoa(peerAddress));
}
else
{
SERVER_ID serverID;
serverID.dwID = lpSessionData->GetServerID();
CSessionData::SessionState eSessionState = lpSessionData->GetSessionState();
if ((serverID.GetType() == CServerSetup::AuthServer && CSessionData::SE_USER_ENABLED != eSessionState) ||
(serverID.GetType() == CServerSetup::GameServer && CSessionData::SE_CHAR_ENABLED != eSessionState))
{
ERRLOG3(g_Log, "UID:%10u / ServerID:0x%08X / ST:%s / 과금 만료 접속 끊기 실패 : 유저나 캐릭터가 비활성화되어 있습니다",
lpSessionData->GetUID(), serverID.dwID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
else if(!SendPacket::UserKill(*lpSessionData))
{
ERRLOG3(g_Log, "UID:%10u / ServerID:0x%08X / ST:%s / 과금 만료 접속 끊기 실패 : 접속 끊기 패킷 보내기 실패",
lpSessionData->GetUID(), serverID.dwID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
}
return true;
}
bool CUIDDispatch::ParseUserKill(PktUK* lpPktUK)
{
using namespace DataStorage;
// 접속 DB를 전부 뒤져서, 계정과 IP가 일치하는 넘한테 뜨거운 맛을 보여 준다.
CSessionData* lpSessionData =
CSessionDataMgr::GetInstance().GetOpenSession(lpPktUK->m_dwUserID);
if(0 == lpSessionData)
{
ERRLOG1(g_Log, "UID:%10u / UID 서버 유저 접속 끊기 실패 : 유저가 없습니다", lpPktUK->m_dwUserID);
}
else
{
SERVER_ID serverID;
serverID.dwID = lpSessionData->GetServerID();
CSessionData::SessionState eSessionState = lpSessionData->GetSessionState();
if ((serverID.GetType() == CServerSetup::AuthServer && CSessionData::SE_USER_ENABLED != eSessionState) ||
(serverID.GetType() == CServerSetup::GameServer && CSessionData::SE_CHAR_ENABLED != eSessionState))
{
ERRLOG3(g_Log, "UID:%10u / ServerID:0x%08X / ST:%s / UID 서버 유저 접속 끊기 실패 : 유저나 캐릭터가 비활성화되어 있습니다",
lpPktUK->m_dwUserID, serverID.dwID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
else if(!SendPacket::UserKill(*lpSessionData))
{
ERRLOG3(g_Log, "UID:%10u / ServerID:0x%08X / ST:%s / UID 서버 유저 접속 끊기 실패 : 접속 끊기 패킷 보내기 실패",
lpPktUK->m_dwUserID, serverID.dwID, g_szSessionStateString[lpSessionData->GetSessionState()]);
}
}
return true;
}
}

View File

@@ -0,0 +1,58 @@
#ifndef _DBAGENT_SERVER_UID_DISPATCH_H_
#define _DBAGENT_SERVER_UID_DISPATCH_H_
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
// forward decl.
struct PktBase;
struct PktUUTAck;
struct PktBTN;
struct PktHanBTN;
struct PktHanUserKill;
struct PktUK;
struct PktSLAck;
namespace DBAgent
{
extern const char* g_szPktUUTString[PktUUT::MAX_UPDATE_TYPE];
class CUIDDispatch : public CRylServerDispatch
{
public:
static CSingleDispatch& GetDispatchTable();
enum Const
{
MAX_PACKET_DISPATCH_PER_PULSE = 100,
MAX_STREAM_BUFFER_SIZE = 16000
};
CUIDDispatch(CSession& Session);
virtual ~CUIDDispatch();
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
private:
bool ParseServerLoginAck(PktSLAck* lpPktSLAck);
bool ParseServerLogoutAck(PktBase* lpPktBase);
bool ParseUpdateUIDTable(PktUUTAck* lpPktUUTAck);
bool ParseBillingTimeNotify(PktBTN* lpPktBTN); // 한국 과금 경고 메시지
bool ParseBillingTimeCheckNotify(PktBTN* lpPktBTN); // 대만 과금 경고 메시지
bool ParseHanBTNWarning(PktHanBTN* lpPktHanBTN); // 한국 통합빌링 과금 경고 메시지
bool ParseHanBTNUserKill(PktHanUserKill* lpPktHanUserKill); // 한국 통합빌링 과금 접속 끊기
bool ParseUserKill(PktUK* lpPktUK); // 접속 끊기
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
#ifndef _DBAGENT_SERVER_PARSE_CASTLE_H_
#define _DBAGENT_SERVER_PARSE_CASTLE_H_
class CSendStream;
struct PktBase;
namespace DBAgent
{
namespace ParseCastle
{
bool CastleCmd(CSendStream& SendStream, PktBase* lpPktBase);
bool SiegeArmsCmd(CSendStream& SendStream, PktBase* lpPktBase);
bool SetCastleRight(CSendStream& SendStream, PktBase* lpPktBase);
bool SetCampRight(CSendStream& SendStream, PktBase* lpPktBase);
bool CreateCamp(CSendStream& SendStream, PktBase* lpPktBase);
bool CreateSiegeArms(CSendStream& SendStream, PktBase* lpPktBase);
bool CampCmd(CSendStream& SendStream, PktBase* lpPktBase);
bool CampMessage(CSendStream& SendStream, PktBase* lpPktBase);
bool MiningCampMineralInfo(CSendStream& SendStream, PktBase* lpPktBase);
bool FertilityInfo(CSendStream& SendStream, PktBase* lpPktBase);
bool CampShopInfo(CSendStream& SendStream, PktBase* lpPktBase);
bool CastleTaxMove(CSendStream& SendStream, PktBase* lpPktBase);
bool CastleMineralInfo(CSendStream& SendStream, PktBase* lpPktBase);
bool WarOnOff(CSendStream& SendStream, PktBase* lpPktBase);
bool StatueCmd(CSendStream& SendSream, PktBase* lpPktBase);
bool RealmPoint(CSendStream& SendSream, PktBase* lpPktBase);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
#ifndef _DBAGENT_SERVER_PARSE_CHAR_MANAGE_H_
#define _DBAGENT_SERVER_PARSE_CHAR_MANAGE_H_
// forward decl;
class CSendStream;
struct PktDD;
struct PktBase;
namespace DBAgent
{
namespace DataStorage
{
// forward decl.
class CItemSerialMgr;
}
namespace ParseCharManage
{
// --------------------------------------------------------------------
// 캐릭터 관리 및 세션 메소드
bool Parse(CSendStream& SendStream, unsigned long dwServerID,
Item::CItemSerialMgr& itemSerialMgr, PktDD* lpPktDD);
// --------------------------------------------------------------------
// 배틀그라운드 서버군 관련 메소드.
// 배섭 게임서버가 중계서버로 캐릭터 슬롯 정보 요청.
bool BGServerCharSlot(CSendStream& SendStream, PktBase* lpPktBase);
// 서버통합 관련 메소드
bool UnifiedCharSelect(CSendStream& SendStream, PktBase* lpPktBase);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
#ifndef _DBAGENT_SERVER_PARSE_CHAR_UPDATE_H_
#define _DBAGENT_SERVER_PARSE_CHAR_UPDATE_H_
#include <Network/Packet/PacketStruct/CharLoginOutPacket.h>
// forward delc.
class CSendStream;
namespace Item
{
// forward decl.
class CItemSerialMgr;
};
namespace DBAgent
{
namespace ParseCharUpdate
{
// ------------------------------------------------------------------------
// 캐릭터 업데이트 데이터 파싱
bool Parse(CSendStream& SendStream, unsigned long dwServerID,
Item::CItemSerialMgr& itemSerialMgr, PktDBUpdate* lpPktDBUpdate);
// ------------------------------------------------------------------------
// 데이터 업데이트 메서드
bool UpdateDeposit(CSendStream& SendStream, PktBase* lpPktBase);
bool UpdateDepositDB(CSendStream& SendStream, PktBase* lpPktBase);
bool UpdateFriendDB(CSendStream& SendStream, PktBase* lpPktBase);
bool UpdateQuestDB(CSendStream& SendStream, PktBase* lpPktBase);
bool UpdateConfigInfoDB(CSendStream& SendStream, PktBase* lpPktBase);
//--------------------------------------------------------------------------
// 듀얼 관련 정보 저장.
bool SaveEnemy(CSendStream& SendStream, PktBase* lpPktBase);
//--------------------------------------------------------------------------
// 조이스틱 키 관련.
bool UpdateKeyInfo(CSendStream& SendStream, PktBase* lpPktBase);
// 캐쉬아이템 사용
bool UseCashItem(CSendStream& SendStream, PktBase* lpPktBase);
// 엑스트라 이벤트
bool ExtraEvent(CSendStream& SendStream, PktBase* lpPktBase);
}
namespace ParseCharAdmin
{
bool AdminCommandLog(CSendStream& SendStream, PktBase* lpPktBase);
}
}
#endif

View File

@@ -0,0 +1,903 @@
#include "stdafx.h"
#include "ParseGuild.h"
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/GuildPacket.h>
#include <Network/Stream/SendStream.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Network/SendPacket/SendGuild.h>
#include <Community/Guild/GuildDB.h>
#include <Community/Guild/GuildDBMgr.h>
#include <DB/DBComponent.h>
#include <DB/GuildDBComponent.h>
#include <Log/ServerLog.h>
#include <DataStorage/SessionDataMgr.h>
#include <DataStorage/CharacterData.h>
#include <Network/Packet/PacketStruct/CastlePacket.h>
#include <GameTime/GameTimeConstants.h>
#include <GameTime/GameTimeDBMgr.h>
#include <DB/GameDBComponent.h>
namespace DBAgent
{
namespace ParseGuild
{
bool CreateGuild(CSendStream& SendStream, PktBase* lpPktBase)
{
PktCreateGuild* lpPktCreateGuild = static_cast<PktCreateGuild*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
CGuildDB* lpGuild = Guild::CGuildDBMgr::GetInstance().CreateGuild(
lpPktCreateGuild->m_dwCID, lpPktCreateGuild->m_cInclination,
lpPktCreateGuild->m_szGuildName, &wError);
PktCreateGuild pktGCAck;
memset(&pktGCAck, 0, sizeof(PktCreateGuild));
pktGCAck.m_dwCID = lpPktCreateGuild->m_dwCID;
pktGCAck.m_dwGID = (NULL != lpGuild) ? lpGuild->GetGID() : 0;
pktGCAck.m_cInclination = lpPktCreateGuild->m_cInclination;
strncpy(pktGCAck.m_szGuildName, lpPktCreateGuild->m_szGuildName, Guild::MAX_GUILD_NAME_LEN);
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGCAck),
sizeof(PktCreateGuild), CmdCreateGuild, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
using namespace DBAgent::DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(lpPktCreateGuild->m_dwCID);
if(lpSessionData)
{
CCharacterData* lpCharacterData = lpSessionData->GetCharacterData();
if(lpCharacterData)
{
// edith 2008.11.24 길드생성시 전쟁 자동참가
lpCharacterData->SetGuildWarFlag(Creature::WAR_ON);
PktWarOnOff* lpPktWarOnOffAck = reinterpret_cast<PktWarOnOff*>(SendStream.GetBuffer(sizeof(PktWarOnOff)));
if (lpPktWarOnOffAck)
{
lpPktWarOnOffAck->m_dwCID = lpCharacterData->GetCID();
lpPktWarOnOffAck->m_cType = GameTime::GUILD;
lpPktWarOnOffAck->m_cFlag = Creature::WAR_ON;
SendStream.WrapHeader(sizeof(PktWarOnOff), CmdWarOnOff, 0, 0);
}
}
}
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGCAck), sizeof(PktCreateGuild), CmdCreateGuild));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGCAck),
sizeof(PktCreateGuild), CmdCreateGuild);
}
return true;
}
return false;
}
bool GuildCmd(CSendStream& SendStream, PktBase* lpPktBase)
{
PktGuildCmd* lpPktGuildCmd = static_cast<PktGuildCmd*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwGID = lpPktGuildCmd->m_dwGID;
unsigned long dwSenderID = lpPktGuildCmd->m_dwSenderID;
unsigned long dwReferenceID = lpPktGuildCmd->m_dwReferenceID;
unsigned short wCmd = lpPktGuildCmd->m_wCmd;
using namespace Guild;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (0 == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
switch (wCmd)
{
case PktGuildCmd::GC_JOIN:
{
// 가입한 멤버 정보를 뒤에 붙여 다른 크기의 패킷을 만들기 때문에 함수 내에서 독자적으로 패킷을 보낸다.
lpGuild->SendJoinMember(&SendStream, dwSenderID, static_cast<unsigned char>(dwReferenceID));
return true;
}
case PktGuildCmd::GC_TACTICS:
{
// 용병 가입 신청.
lpGuild->SendJoinTacticsMember(&SendStream, dwSenderID, static_cast<unsigned char>(dwReferenceID), PktGuildCmd::GC_TACTICS);
return true;
}
case PktGuildCmd::GC_TACTICS_JOIN:
{
// 용병 가입 신청.
lpGuild->SendJoinTacticsMember(&SendStream, dwSenderID, static_cast<unsigned char>(dwReferenceID), PktGuildCmd::GC_TACTICS_JOIN);
return true;
}
case PktGuildCmd::GC_TACTICS_TITLE:
case PktGuildCmd::GC_TACTICS_REQUEST:
{
using namespace DBAgent::DataStorage;
// 용병 허가.
unsigned char cTitle = static_cast<unsigned char>(dwReferenceID);
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwSenderID);
if(wCmd==PktGuildCmd::GC_TACTICS_REQUEST)
goto lb_request;
if(CGameTimeDBMgr::GetInstance().IsGuildWarTime())
{
if(lpSessionData)
{
CCharacterData* lpCharacterData = lpSessionData->GetCharacterData();
if(lpCharacterData)
{
SendPacket::GuildCmd(&SendStream, dwGID, dwSenderID, COMMON, PktGuildCmd::GC_TACTICS_REQUEST, NULL, NULL, wError);
}
else
{
goto lb_error;
}
}
else
{
lb_error:
PktGuildCmd pktGuildCmd;
memset(&pktGuildCmd, 0, sizeof(PktGuildCmd));
strcpy(pktGuildCmd.m_szSenderName, lpPktGuildCmd->m_szSenderName);
pktGuildCmd.m_dwGID = dwGID;
pktGuildCmd.m_dwSenderID = dwSenderID;
pktGuildCmd.m_dwReferenceID = COMMON;
pktGuildCmd.m_wCmd = PktGuildCmd::GC_TACTICS_TITLE;
SendStream.WrapCompress(reinterpret_cast<char*>(&pktGuildCmd), sizeof(PktGuildCmd), CmdGuildCmd, 0, PktGuildCmd::FAIL_TACTICS_LOGOUT);
}
}
else
{
lb_request:
lpGuild->SetTacticsMember(dwSenderID, Guild::TACTICS);
lpGuild->SetTitle(dwSenderID, COMMON);
SendPacket::GuildCmd(&SendStream, dwGID, dwSenderID, COMMON, PktGuildCmd::GC_TACTICS_TITLE, NULL, NULL, wError);
DBComponent::GuildDB::UpdateGuildMemberTactics(CDBSingleObject::GetInstance(), lpGuild->GetGID(), dwSenderID, Guild::TACTICS);
if(lpSessionData)
{
CCharacterData* lpCharacterData = lpSessionData->GetCharacterData();
if(lpCharacterData)
{
lpCharacterData->SetGuildWarFlag(Creature::WAR_ON);
PktWarOnOff* lpPktWarOnOffAck = reinterpret_cast<PktWarOnOff*>(SendStream.GetBuffer(sizeof(PktWarOnOff)));
if (lpPktWarOnOffAck)
{
lpPktWarOnOffAck->m_dwCID = lpCharacterData->GetCID();
lpPktWarOnOffAck->m_cType = GameTime::GUILD;
lpPktWarOnOffAck->m_cFlag = Creature::WAR_ON;
SendStream.WrapHeader(sizeof(PktWarOnOff), CmdWarOnOff, 0, 0);
}
}
}
else
{
DBComponent::GameDB::UpdateGuildWarFlag(CDBSingleObject::GetInstance(), dwSenderID, Creature::WAR_ON);
}
}
return true;
}
case PktGuildCmd::GC_TACTICS_KICK:
case PktGuildCmd::GC_TACTICS_LEAVE:
{
// 용병 퇴출 및 탈퇴.
if (false == lpGuild->LeaveMember(dwSenderID))
{
wError = PktBase::SERVER_ERROR;
}
SendPacket::GuildCmd(&SendStream, dwGID, dwSenderID, dwReferenceID, wCmd, NULL, NULL, wError);
using namespace DBAgent::DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwSenderID);
if(lpSessionData)
{
CCharacterData* lpCharacterData = lpSessionData->GetCharacterData();
if(lpCharacterData)
{
lpCharacterData->SetGuildWarFlag(Creature::WAR_OFF);
PktWarOnOff* lpPktWarOnOffAck = reinterpret_cast<PktWarOnOff*>(SendStream.GetBuffer(sizeof(PktWarOnOff)));
if (lpPktWarOnOffAck)
{
lpPktWarOnOffAck->m_dwCID = lpCharacterData->GetCID();
lpPktWarOnOffAck->m_cType = GameTime::GUILD;
lpPktWarOnOffAck->m_cFlag = Creature::WAR_OFF;
SendStream.WrapHeader(sizeof(PktWarOnOff), CmdWarOnOff, 0, 0);
}
}
}
else
{
DBComponent::GameDB::UpdateGuildWarFlag(CDBSingleObject::GetInstance(), dwSenderID, Creature::WAR_OFF);
}
return true;
}
case PktGuildCmd::GC_SETUP_TITLE:
{
unsigned char cTitle = static_cast<unsigned char>(dwReferenceID);
// 길드 마스터 탈퇴
if (dwSenderID == lpGuild->GetMaster().m_dwCID)
{
unsigned long dwNewMaster = lpGuild->SetNewMaster();
if (0 == dwNewMaster)
{
DETLOG1(g_Log, "GID:%10u 길드가 해체되었습니다. - 길드마스터 탈퇴", lpGuild->GetGID());
CGuildDBMgr::GetInstance().DissolveGuild(
lpGuild->GetGID(), PktCreateGuild::NONE_NEXT_GUILDMASTER_BY_GUILDMASTER_OUT);
break;
}
SendPacket::GuildCmd(&SendStream, dwGID, dwNewMaster, MASTER, PktGuildCmd::GC_SETUP_TITLE, NULL, NULL, wError);
DETLOG3(g_Log, "GID:%10u 길드마스터(이전:%10u, 현재:%10u)가 변경되었습니다. - 길드마스터 탈퇴",
lpGuild->GetGID(), dwSenderID, dwNewMaster);
}
// 길드 마스터 권한 양도
if (MASTER == cTitle)
{
MemberInfo PreMasterInfo = lpGuild->GetMaster();
lpGuild->SetTitle(PreMasterInfo.m_dwCID, COMMON);
SendPacket::GuildCmd(&SendStream, dwGID, PreMasterInfo.m_dwCID, COMMON, PktGuildCmd::GC_SETUP_TITLE, NULL, NULL, wError);
DETLOG3(g_Log, "GID:%10u 길드마스터(이전:%10u, 현재:%10u)가 변경되었습니다. - 길드마스터 권한 양도",
lpGuild->GetGID(), PreMasterInfo.m_dwCID, dwSenderID);
}
lpGuild->SetTitle(dwSenderID, cTitle);
if(cTitle==COMMON)
{
using namespace DBAgent::DataStorage;
// edith 2008.03.15 일반 길드원으로 타이틀을 변경하는데 SenderID가 아닌 dwGID 에서 얻어왔다 잘못됐다.
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwSenderID);
// CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwGID);
if(lpSessionData)
{
CCharacterData* lpCharacterData = lpSessionData->GetCharacterData();
if(lpCharacterData)
{
// edith 2008.11.24 길드마스터가 될시에 전쟁 자동참가
// edith 2009.05.20 일반 길드원이 될때 전쟁자동참여 OFF 로 설정.
lpCharacterData->SetGuildWarFlag(Creature::WAR_OFF);
PktWarOnOff* lpPktWarOnOffAck = reinterpret_cast<PktWarOnOff*>(SendStream.GetBuffer(sizeof(PktWarOnOff)));
if (lpPktWarOnOffAck)
{
lpPktWarOnOffAck->m_dwCID = lpCharacterData->GetCID();
lpPktWarOnOffAck->m_cType = GameTime::GUILD;
lpPktWarOnOffAck->m_cFlag = Creature::WAR_OFF;
SendStream.WrapHeader(sizeof(PktWarOnOff), CmdWarOnOff, 0, 0);
}
}
}
}
break;
}
case PktGuildCmd::GC_KICK:
{
// 길드 마스터의 경우 삭제시 킥 명령이 온다.
if (dwSenderID == lpGuild->GetMaster().m_dwCID)
{
unsigned long dwNewMaster = lpGuild->SetNewMaster();
if (0 == dwNewMaster)
{
DETLOG1(g_Log, "GID:%10u 길드가 해체되었습니다. - 길드마스터 삭제", lpGuild->GetGID());
CGuildDBMgr::GetInstance().DissolveGuild(lpGuild->GetGID(),
PktCreateGuild::NONE_NEXT_GUILDMASTER_BY_GUILDMASTER_DELETED);
break;
}
SendPacket::GuildCmd(&SendStream, dwGID, dwNewMaster, MASTER, PktGuildCmd::GC_SETUP_TITLE, NULL, NULL, wError);
DETLOG3(g_Log, "GID:%10u 길드마스터(이전:%10u, 현재:%10u)가 변경되었습니다. - 길드마스터 삭제",
lpGuild->GetGID(), dwSenderID, dwNewMaster);
}
if (false == lpGuild->LeaveMember(dwSenderID))
{
wError = PktBase::SERVER_ERROR;
}
using namespace DBAgent::DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwSenderID);
if(lpSessionData)
{
CCharacterData* lpCharacterData = lpSessionData->GetCharacterData();
if(lpCharacterData)
{
lpCharacterData->SetGuildWarFlag(Creature::WAR_OFF);
PktWarOnOff* lpPktWarOnOffAck = reinterpret_cast<PktWarOnOff*>(SendStream.GetBuffer(sizeof(PktWarOnOff)));
if (lpPktWarOnOffAck)
{
lpPktWarOnOffAck->m_dwCID = lpCharacterData->GetCID();
lpPktWarOnOffAck->m_cType = GameTime::GUILD;
lpPktWarOnOffAck->m_cFlag = Creature::WAR_OFF;
SendStream.WrapHeader(sizeof(PktWarOnOff), CmdWarOnOff, 0, 0);
}
}
}
else
{
DBComponent::GameDB::UpdateGuildWarFlag(CDBSingleObject::GetInstance(), dwSenderID, Creature::WAR_OFF);
}
break;
}
}
}
return SendPacket::GuildCmd(&SendStream, dwGID, dwSenderID, dwReferenceID, wCmd, NULL, NULL, wError);
}
bool GuildMark(CSendStream& SendStream, PktBase* lpPktBase)
{
PktGuildMark* lpPktGuildMark = static_cast<PktGuildMark*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwCID = lpPktGuildMark->m_dwCID;
unsigned long dwGID = lpPktGuildMark->m_dwGID;
unsigned long dwGold = 0;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (0 == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
lpGuild->SetMark(lpPktGuildMark->m_szMark);
dwGold = lpGuild->GetGold();
}
PktGuildMark pktGuildMark;
memset(&pktGuildMark, 0, sizeof(PktGuildMark));
pktGuildMark.m_dwCID = dwCID;
pktGuildMark.m_dwGID = dwGID;
pktGuildMark.m_dwGold = dwGold;
memcpy(pktGuildMark.m_szMark, lpPktGuildMark->m_szMark, MAX_MARK_SIZE);
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildMark),
sizeof(PktGuildMark), CmdGuildMark, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildMark), sizeof(PktGuildMark), CmdGuildMark));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGuildMark),
sizeof(PktGuildMark), CmdGuildMark);
}
return true;
}
return false;
}
bool GuildLevel(CSendStream& SendStream, PktBase* lpPktBase)
{
PktGuildLevel* lpPktGuildLevel = static_cast<PktGuildLevel*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwGID = lpPktGuildLevel->m_dwUID;
unsigned char cLevel = lpPktGuildLevel->m_cLevel;
unsigned long dwGold = 0;
using namespace Guild;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (NULL == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
lpGuild->SetLevel(cLevel);
dwGold = lpGuild->GetGold();
}
PktGuildLevel pktGuildLevel;
memset(&pktGuildLevel, 0, sizeof(PktGuildLevel));
pktGuildLevel.m_dwUID = dwGID;
pktGuildLevel.m_cLevel = cLevel;
pktGuildLevel.m_dwGold = dwGold;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildLevel),
sizeof(PktGuildLevel), CmdGuildLevel, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildLevel), sizeof(PktGuildLevel), CmdGuildLevel));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGuildLevel),
sizeof(PktGuildLevel), CmdGuildLevel);
}
return true;
}
return false;
}
bool GuildRelation(CSendStream& SendStream, PktBase* lpPktBase)
{
PktGuildRelation* lpPktGuildRelation = static_cast<PktGuildRelation*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwCID = lpPktGuildRelation->m_dwCID;
unsigned long dwGID = lpPktGuildRelation->m_dwGID;
unsigned long dwTargetGID = lpPktGuildRelation->m_dwTargetGID;
unsigned long dwValue = lpPktGuildRelation->m_dwValue;
char cSubCmd = lpPktGuildRelation->m_cSubCmd;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
CGuildDB* lpTargetGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwTargetGID));
if (NULL == lpGuild || NULL == lpTargetGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
switch (cSubCmd)
{
case PktGuildRelation::GR_HOSTILITY:
{
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwTargetGID, Guild::HOSTILITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
break;
}
case PktGuildRelation::GR_PEACE:
{
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwTargetGID, Guild::NEUTRALITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
break;
}
case PktGuildRelation::GR_HOSTILITYDEL:
{
// 내가 TargetGuild에게 평화허락을 한다.
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwTargetGID, Guild::TARGET_NEUTRALITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
break;
}
case PktGuildRelation::GR_ALERT:
{
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwTargetGID, Guild::ALERT_HOSTILITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
break;
}
case PktGuildRelation::GR_COUNTER:
{
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwTargetGID, Guild::COUNTER_HOSTILITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
break;
}
case PktGuildRelation::GR_REQUEST:
{
CGuildDB* lpHostilityGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwValue));
if (NULL == lpHostilityGuild)
{
wError = PktGuildRelation::SERVER_ERROR;
}
else
{
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwValue, Guild::NEUTRALITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
else
{
if (!CGuildDBMgr::GetInstance().SetRelation(dwGID, dwTargetGID, Guild::HOSTILITY))
{
wError = PktGuildRelation::SERVER_ERROR;
}
}
}
break;
}
}
}
PktGuildRelation pktGuildRelation;
memset(&pktGuildRelation, 0, sizeof(PktGuildRelation));
pktGuildRelation.m_dwCID = dwCID;
pktGuildRelation.m_dwGID = dwGID;
pktGuildRelation.m_dwTargetGID = dwTargetGID;
pktGuildRelation.m_dwValue = dwValue;
pktGuildRelation.m_cSubCmd = cSubCmd;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildRelation),
sizeof(PktGuildRelation), CmdGuildRelation, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildRelation),
sizeof(PktGuildRelation), CmdGuildRelation));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGuildRelation),
sizeof(PktGuildRelation), CmdGuildRelation);
}
return true;
}
return false;
}
bool GuildInclination(CSendStream& SendStream, PktBase* lpPktBase)
{
// 더이상 길드 국적은 변경할 수 없습니다. (2004-11-22 by 로딘)
/*
PktGuildInclination* lpPktInclination = static_cast<PktGuildInclination*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwGID = lpPktInclination->m_dwUID;
unsigned char cInclination = lpPktInclination->m_cInclination;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (NULL == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
lpGuild->SetInclination(cInclination);
}
PktGuildInclination pktGuildInclination;
memset(&pktGuildInclination, 0, sizeof(PktGuildInclination));
pktGuildInclination.m_dwUID = dwGID;
pktGuildInclination.m_cInclination = cInclination;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildInclination),
sizeof(PktGuildInclination), CmdGuildInclination, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildInclination),
sizeof(PktGuildInclination), CmdGuildInclination));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGuildInclination),
sizeof(PktGuildInclination), CmdGuildInclination);
}
return true;
}
*/
return false;
}
bool SetGuildRight(CSendStream& SendStream, PktBase* lpPktBase)
{
using namespace Guild;
PktGuildRight* lpPktGuildRight = static_cast<PktGuildRight *>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwGID = lpPktGuildRight->m_dwUID;
GuildRight guildRight = lpPktGuildRight->m_GuildRight;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (NULL == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
lpGuild->SetRight(guildRight);
}
PktGuildRight pktGuildRight;
memset(&pktGuildRight, 0, sizeof(PktGuildRight));
pktGuildRight.m_dwUID = dwGID;
pktGuildRight.m_GuildRight = guildRight;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildRight),
sizeof(PktGuildRight), CmdGuildRight, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildRight), sizeof(PktGuildRight), CmdGuildRight));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGuildRight),
sizeof(PktGuildRight), CmdGuildRight);
}
return true;
}
return false;
}
bool GuildSafe(CSendStream& SendStream, PktBase* lpPktBase)
{
PktGuildSafeAck* lpPktGuildSafe = reinterpret_cast<PktGuildSafeAck *>(lpPktBase);
unsigned wError = PktBase::NO_SERVER_ERR;
unsigned long dwCID = lpPktGuildSafe->m_dwCID;
unsigned long dwGID = lpPktGuildSafe->m_dwGID;
unsigned long dwSafeGold = lpPktGuildSafe->m_dwSafeGold;
unsigned long dwCharGold = lpPktGuildSafe->m_dwCharGold;
unsigned char cCmd = lpPktGuildSafe->m_cCmd;
using namespace DBAgent::DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwCID);
CCharacterData* lpCharacterData = NULL;
if(lpSessionData)
lpCharacterData = lpSessionData->GetCharacterData();
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (NULL == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
switch (cCmd)
{
// 출금
case PktGuildSafe::SC_WITHDRAWAL:
{
if (false == lpGuild->DeductGold(dwCharGold))
{
wError = PktGuildSafe::FAIL_NOT_ENOUGH_MONEY;
}
dwSafeGold = dwCharGold;
break;
}
// 입금
case PktGuildSafe::SC_DEPOSIT:
{
// edith 2008.03.15 캐릭터의 골드를 뺀다.
if(false == lpCharacterData->DeductGold(dwCharGold))
{
wError = PktGuildSafe::FAIL_NOT_CHAR_MONEY;
}
else if (false == lpGuild->AddGold(dwCharGold))
{
// 되돌린다 금액을
lpCharacterData->AddGold(dwCharGold);
wError = PktGuildSafe::FAIL_NOT_GUILD_DEPOSIT;
}
dwSafeGold = dwCharGold;
break;
}
// 길드 보너스
case PktGuildSafe::SC_BONUS:
{
if (false == lpGuild->AddGold(dwCharGold))
{
wError = PktGuildSafe::FAIL_NOT_GUILD_DEPOSIT;
}
dwSafeGold = dwCharGold;
}
break;
// 분배
case PktGuildSafe::SC_RELEASE:
{
unsigned long dwPreSafeGold = lpGuild->GetGold();
dwCharGold = lpGuild->ReleaseGold(dwCharGold);
if (0 == dwCharGold)
{
wError = PktGuildSafe::FAIL_NOT_ENOUGH_MONEY;
break;
}
dwSafeGold = dwPreSafeGold - lpGuild->GetGold();
break;
}
default:
wError = PktBase::SERVER_ERROR;
break;
}
}
PktGuildSafeAck pktGuildSafeAck;
memset(&pktGuildSafeAck, 0, sizeof(PktGuildSafeAck));
pktGuildSafeAck.m_dwCID = dwCID;
pktGuildSafeAck.m_dwGID = dwGID;
pktGuildSafeAck.m_dwSafeGold = dwSafeGold;
pktGuildSafeAck.m_dwCharGold = dwCharGold;
pktGuildSafeAck.m_cCmd = cCmd;
strncpy(pktGuildSafeAck.m_szCharName,
lpPktGuildSafe->m_szCharName, Guild::MAX_MEMBER_NAME_LEN);
if (!DBComponent::GuildDB::UpdateGuildGold(
CDBSingleObject::GetInstance(), lpGuild->GetGID(), lpGuild->GetGold()))
{
wError = PktGuildSafe::FAIL_NOT_GUILD_UPDATE;
}
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildSafeAck),
sizeof(PktGuildSafeAck), CmdGuildSafe, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildSafeAck), sizeof(PktGuildSafeAck), CmdGuildSafe));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGuildSafeAck),
sizeof(PktGuildSafeAck), CmdGuildSafe);
}
return true;
}
return false;
}
bool GuildMemberInfoUpdate(CSendStream& SendStream, PktBase* lpPktBase)
{
PktGuildMemberInfoUpdate* lpPktGMIU = static_cast<PktGuildMemberInfoUpdate*>(lpPktBase);
unsigned short wError = PktBase::NO_SERVER_ERR;
unsigned long dwGID = lpPktGMIU->m_dwGID;
unsigned long dwCID = lpPktGMIU->m_dwCID;
CGuildDB* lpGuild = static_cast<CGuildDB*>(CGuildDBMgr::GetInstance().GetGuild(dwGID));
if (NULL == lpGuild)
{
wError = PktBase::SERVER_ERROR;
}
else
{
lpGuild->UpdateMemberInfo(dwCID,
lpPktGMIU->m_MemberListInfo, lpPktGMIU->m_MemberDetailInfo);
}
PktGuildMemberInfoUpdate pktGMIUAck;
memset(&pktGMIUAck, 0, sizeof(PktGuildMemberInfoUpdate));
pktGMIUAck.m_dwGID = dwGID;
pktGMIUAck.m_dwCID = dwCID;
pktGMIUAck.m_MemberListInfo = lpPktGMIU->m_MemberListInfo;
pktGMIUAck.m_MemberDetailInfo = lpPktGMIU->m_MemberDetailInfo;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGMIUAck),
sizeof(PktGuildMemberInfoUpdate), CmdGuildMemberInfoUpdate, 0, wError))
{
if (PktBase::NO_SERVER_ERR == wError)
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGMIUAck),
sizeof(PktGuildMemberInfoUpdate), CmdGuildMemberInfoUpdate));
}
else
{
SendStream.PutBuffer(reinterpret_cast<char*>(&pktGMIUAck),
sizeof(PktGuildMemberInfoUpdate), CmdGuildMemberInfoUpdate);
}
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,25 @@
#ifndef _DBAGENT_SERVER_PARSE_GUILD_H_
#define _DBAGENT_SERVER_PARSE_GUILD_H_
// forward delc.
class CSendStream;
struct PktBase;
namespace DBAgent
{
namespace ParseGuild
{
bool CreateGuild(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildCmd(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildMark(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildLevel(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildRelation(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildInclination(CSendStream& SendStream, PktBase* lpPktBase);
bool SetGuildRight(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildSafe(CSendStream& SendStream, PktBase* lpPktBase);
bool GuildMemberInfoUpdate(CSendStream& SendStream, PktBase* lpPktBase);
}
}
#endif

View File

@@ -0,0 +1,345 @@
#include "stdafx.h"
#include "ParseMoveZone.h"
#include <Creature/CreatureManager.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Network/SendPacket/SendMoveZone.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <DataStorage/CharacterData.h>
#include <DataStorage/SessionData.h>
#include <DataStorage/SessionDataMgr.h>
#include <Log/ServerLog.h>
#include <Utility/Setup/ServerSetup.h>
#include <GameTime/GameTimeDBMgr.h>
namespace DBAgent
{
namespace ParseMoveZone
{
bool CharMoveZone(CSendStream& SendStream, PktSZMvD* lpPktSZMvD);
bool ServerZone(CSendStream& SendStream, PktSA* lpPktSA);
bool ServerZoneEnd(CSendStream& SendStream, PktDD* lpPktDD);
bool Parse(CSendStream& SendStream, PktBase* lpPktBase)
{
bool bResult = false;
PktDD* lpPktDD = static_cast<PktDD*>(lpPktBase);
switch (lpPktDD->m_wCmd)
{
case PktDD::SCmdCharMoveZone:
bResult = CharMoveZone(SendStream, static_cast<PktSZMvD*>(lpPktDD));
break;
case PktDD::SCmdServerZone:
bResult = ServerZone(SendStream, static_cast<PktSA*>(lpPktDD));
break;
case PktDD::SCmdServerZoneEnd:
bResult = ServerZoneEnd(SendStream, lpPktDD);
break;
default:
ERRLOG1(g_Log, "ZoneMove 패킷 처리 에러 : 알 수 없는 패킷 CMD:0x%02X를 받았습니다.",
lpPktDD->m_wCmd);
bResult = true;
break;
}
return bResult;
}
class CFindGameServerDispatch
{
public:
CFindGameServerDispatch(CGameDispatch*& lpGameDispatch, SERVER_ID serverID)
: m_lpGameDispatch(lpGameDispatch), m_serverID(serverID)
{
m_lpGameDispatch = 0;
}
bool operator() (unsigned long dwServerID, CPacketDispatch& packetDispatch)
{
if(0 == m_lpGameDispatch)
{
SERVER_ID serverID;
serverID.dwID = dwServerID;
// 서버 ID가 같으면 선택, 다르더라도, 채널만 -1이고 다른게 같으면 선택.
if ((serverID.dwID == m_serverID.dwID) ||
(-1 == m_serverID.GetChannel() &&
serverID.GetZone() == m_serverID.GetZone() &&
serverID.GetGroup() == m_serverID.GetGroup() &&
serverID.GetType() == m_serverID.GetType()))
{
m_lpGameDispatch = &static_cast<CGameDispatch&>(packetDispatch);
}
}
return true;
}
private:
CGameDispatch*& m_lpGameDispatch;
SERVER_ID m_serverID;
};
bool CharMoveZone(CSendStream& SendStream, PktSZMvD* lpPktSZMvD)
{
unsigned long dwRequestKey = lpPktSZMvD->m_dwRequestKey;
unsigned long dwUID = lpPktSZMvD->m_dwUserID;
const POS& Pos = lpPktSZMvD->m_NewPos;
char cZone = lpPktSZMvD->m_cZone;
char cChannel = lpPktSZMvD->m_cChannel;
#ifdef ENABLE_PACKET_LOG
DETLOG4(g_PacketLog, "ParseMoveZone::CharMoveZone : UID:%10u / CID:%10u / SessionID:%10u / ServerID:0x%08X / ",
dwUID, 0, 0, 0);
#endif
unsigned short usError = 0;
using namespace DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(dwUID);
CCharacterData* lpCharacterData = 0;
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::GameServer;
serverID.sID.Group = CServerSetup::GetInstance().GetServerGroup();
serverID.sID.Channel = cChannel;
serverID.sID.ID = cZone;
CGameDispatch* lpGameDispatch = 0;
CGameDispatch::GetDispatchTable().Process(
CFindGameServerDispatch(lpGameDispatch, serverID));
if (0 == lpSessionData)
{
ERRLOG1(g_Log, "UID:%10u / 캐릭터 이동 실패 : 세션이 열려 있지 않습니다.", dwUID);
usError = PktSZMvDAck::FAIL_INVALID_CHAR;
}
else if (0 == (lpCharacterData = lpSessionData->GetCharacterData()))
{
ERRLOG1(g_Log, "UID:%10u / 캐릭터 이동 실패 : 캐릭터 데이터가 로드되지 않았습니다.", dwUID);
usError = PktSZMvDAck::FAIL_INVALID_CHAR;
}
else if (0 == lpGameDispatch)
{
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 캐릭터 이동 실패 : 서버가 없습니다.",
dwUID, serverID.dwID);
usError = PktSZMvDAck::FAIL_INVALID_ZONE;
}
else if (0 == lpSessionData->GetAdminLevel())
{
// edith 2009.06.13 석상전 유저 수 체크
if(SERVER_ID::STONE_WAR1 <= cZone && cZone <= SERVER_ID::STONE_WAR3)
{
if (CServerSetup::GetInstance().GetBattleLimit() < lpGameDispatch->GetCharNum())
{
// 사람이 너무 많다.
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 캐릭터 이동 실패 : 사람이 너무 많습니다.",
dwUID, serverID.dwID);
usError = PktSZMvDAck::FAIL_PERSONNEL_OVER;
}
else
{
int maxDefaultUser = 10;
float limitPer = (float)CServerSetup::GetInstance().GetBattleLimitPer()/100.f;
if(limitPer < 1.0f)
limitPer = 1.0f;
int akhanUser = lpGameDispatch->GetCharNum(CClass::AKHAN);
int humanUser = lpGameDispatch->GetCharNum(CClass::HUMAN);
// 내가 인간이고, 인간이 아칸보다 1.5배 많은 상황이면 입장 불가.
if (CClass::HUMAN == lpCharacterData->GetRace())
{
int overCount = (int)((float)akhanUser * limitPer) - akhanUser;
if(overCount < maxDefaultUser)
overCount = maxDefaultUser;
int overUser = akhanUser + overCount;
if(overUser < lpGameDispatch->GetCharNum(CClass::HUMAN))
{
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 캐릭터 이동 실패 : 인간종족 불균형.",
dwUID, serverID.dwID);
usError = PktSZMvDAck::FAIL_PERSONNEL_OVER;
}
}
// 내가 아칸이고, 아칸이 인간보다 1.5배 많은 상황이면 입장 불가.
else if (CClass::AKHAN == lpCharacterData->GetRace())
{
int overCount = (int)((float)humanUser * limitPer) - humanUser;
if(overCount < maxDefaultUser)
overCount = maxDefaultUser;
int overUser = humanUser + overCount;
if(overUser < lpGameDispatch->GetCharNum(CClass::AKHAN))
{
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 캐릭터 이동 실패 : 아칸종족 불균형.",
dwUID, serverID.dwID);
usError = PktSZMvDAck::FAIL_PERSONNEL_OVER;
}
}
}
}
else if (SERVER_ID::ZONE3 == cZone)
{
// 배틀그라운드의 경우 인원 제한 체크
// 2008.10.12 ZONE3번 유저 설정 제거.
ERRLOG3(g_Log, "UID:%10u / 3번 존 접속 시도 : Zone(%d,%d)", dwUID, cZone, cChannel);
usError = PktSZMvDAck::FAIL_INVALID_CHAR;
/*
SYSTEMTIME systemTime;
GetSystemTime(&systemTime);
// 배틀 그라운드 휴식 시간동안에는 각 종족의 초기 존으로 이동 시켜준다.
if ((systemTime.wMinute >= STATUE_REST_TIME_1ST_START && systemTime.wMinute <= STATUE_REST_TIME_1ST_END) ||
(systemTime.wMinute >= STATUE_REST_TIME_2ND_START && systemTime.wMinute <= STATUE_REST_TIME_2ND_END))
{
cZone = lpDataSession->GetCharDataSession().GetCharStartZone(lpCharacterData->GetRace());
}
*/
/* SERVER_ID serverID;
serverID.sID.Type = CServerSetup::GameServer;
serverID.sID.Group = CServerSetup::GetInstance().GetServerGroup();
serverID.sID.Channel = cChannel;
serverID.sID.ID = cZone;
CGameDispatch* lpGameDispatch = 0;
CGameDispatch::GetDispatchTable().Process(
CFindGameServerDispatch(lpGameDispatch, serverID));
if (0 == lpGameDispatch)
{
ERRLOG2(g_Log, "UID:%10u / ServerID:0x%08X / 캐릭터 이동 실패 : 서버가 없습니다.",
dwUID, serverID.dwID);
usError = PktSZMvDAck::FAIL_INVALID_ZONE;
}
else if (CServerSetup::GetInstance().GetBattleLimit() > lpGameDispatch->GetCharNum())
{
// 내가 인간이고, 인간이 아칸보다 1.5배 많은 상황이면 입장 불가.
if (CClass::HUMAN == lpCharacterData->GetRace() &&
lpGameDispatch->GetCharNum(CClass::AKHAN) * 1.5 < lpGameDispatch->GetCharNum(CClass::HUMAN))
{
usError = PktSZMvDAck::FAIL_PERSONNEL_OVER;
}
// 내가 아칸이고, 아칸이 인간보다 1.5배 많은 상황이면 입장 불가.
else if (CClass::AKHAN == lpCharacterData->GetRace() &&
lpGameDispatch->GetCharNum(CClass::HUMAN ) * 1.5 < lpGameDispatch->GetCharNum(CClass::AKHAN))
{
usError = PktSZMvDAck::FAIL_PERSONNEL_OVER;
}
}
*/
}
}
// if(SERVER_ID::STONE_WAR1 <= cZone && cZone <= SERVER_ID::STONE_WAR3)
// usError = PktSZMvDAck::FAIL_PERSONNEL_OVER;
if(0 == usError && 0 != lpSessionData)
{
// 미리 갈 존 설정
if (!lpSessionData->SetMoveZone(cZone, Pos))
{
/*
if(SERVER_ID::ZONE5 == cZone && !CGameTimeDBMgr::GetInstance().IsEnterTime())
{
// 테섭용 신규존 진입제한에 걸렸음.
DETLOG5(g_Log, "UID:%10u / Zone:%2u / X:%f / Y:%f / Z:%f / 캐릭터 이동 실패 : 신규존 진입제한.",
dwUID, cZone, Pos.fPointX, Pos.fPointY, Pos.fPointZ);
}
else
{
ERRLOG5(g_Log, "UID:%10u / Zone:%2u / X:%f / Y:%f / Z:%f / 캐릭터 이동 실패 : 잘못된 존으로 이동 시도.",
dwUID, cZone, Pos.fPointX, Pos.fPointY, Pos.fPointZ);
}
*/
ERRLOG5(g_Log, "UID:%10u / Zone:%2u / X:%f / Y:%f / Z:%f / 캐릭터 이동 실패 : 잘못된 존으로 이동 시도.",
dwUID, cZone, Pos.fPointX, Pos.fPointY, Pos.fPointZ);
usError = PktSZMvDAck::FAIL_INVALID_ZONE;
}
}
// edith 2009.06.28 존이동실패시 전쟁 플래그를 꺼준다.
// gameserver에서 dbagnet로 패킷 전달하게 소스 수정함.
if(0 != usError)
{
if(SERVER_ID::STONE_WAR1 <= cZone && cZone <= SERVER_ID::STONE_WAR3)
lpCharacterData->SetRealmWarFlag(Creature::WAR_OFF);
else if(SERVER_ID::CAPITAL == cZone)
lpCharacterData->SetGuildWarFlag(Creature::WAR_OFF);
}
return (-1 == cChannel || 0 != usError) ?
// 채널이 -1이거나, 에러가 있는 경우 이 패킷을 보냄.
SendPacket::CharMoveZone(SendStream, dwRequestKey, cZone, usError)
: SendPacket::ServerZone(SendStream, dwRequestKey, cZone, cChannel);
}
bool ServerZone(CSendStream& SendStream, PktSA* lpPktSA)
{
unsigned long dwUID = lpPktSA->m_dwUserID;
unsigned short usError = 0;
#ifdef ENABLE_PACKET_LOG
DETLOG4(g_PacketLog, "ParseMoveZone::ServerZone : UID:%10u / CID:%10u / SessionID:%10u / ServerID:0x%08X / ",
dwUID, 0, 0, 0);
#endif
using namespace DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetOpenSession(dwUID);
if (0 == lpSessionData)
{
ERRLOG1(g_Log, "UID:%10u / ServerZone 실패 : 세션이 열려 있지 않습니다.", dwUID);
usError = PktSAAck::SERVER_ERROR;
}
return SendPacket::ServerZone(SendStream,
lpPktSA->m_dwRequestKey, lpPktSA->m_cZone, lpPktSA->m_cChannel, usError);
}
bool ServerZoneEnd(CSendStream& SendStream, PktDD* lpPktDD)
{
#ifdef ENABLE_PACKET_LOG
DETLOG4(g_PacketLog, "ParseMoveZone::ServerZoneEnd : UID:%10u / CID:%10u / SessionID:%10u / ServerID:0x%08X / ",
0, 0, 0, 0);
#endif
return SendPacket::ServerZoneEnd(SendStream, lpPktDD->m_dwRequestKey);
}
}
}

View File

@@ -0,0 +1,17 @@
#ifndef _DBAGENT_SERVER_PARSE_MOVE_ZONE_H_
#define _DBAGENT_SERVER_PARSE_MOVE_ZONE_H_
// forward delc.
class CSendStream;
struct PktBase;
namespace DBAgent
{
namespace ParseMoveZone
{
bool Parse(CSendStream& SendStream, PktBase* lpPktBase);
}
}
#endif

View File

@@ -0,0 +1,386 @@
#include "stdafx.h"
#include "ParseParty.h"
#include <Community/Party/PartyDBInfo.h>
#include <Community/Party/PartyDBMgr.h>
#include <Community/Guild/Guild.h>
#include <Community/Guild/GuildMgr.h>
#include <Network/Stream/SendStream.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketStruct/PartyPacket.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Network/SendPacket/SendParty.h>
#include <Log/ServerLog.h>
#include <DB/DBComponent.h>
#include <DataStorage/SessionData.h>
#include <DataStorage/CharacterData.h>
#include <DataStorage/SessionDataMgr.h>
#include <Community/Guild/Guild.h>
namespace DBAgent
{
namespace ParseParty
{
bool CreateParty(CSendStream& SendStream, PktCPD* lpPktCPD);
bool DeleteParty(CSendStream& SendStream, PktDPD* lpPktDPD);
bool GetPartyInfo(CSendStream& SendStream, PktPID* lpPktPID);
bool TransferLeader(CSendStream& SendStream, PktPMD* lpPktPMD);
bool InsertPartyMember(CSendStream& SendStream, PktPMD* lpPktPMD);
bool DeletePartyMember(CSendStream& SendStream, PktPMD* lpPktPMD);
bool AutoRoutingOn(CSendStream& SendStream, PktPMD* lpPktPMD);
bool AutoRoutingOff(CSendStream& SendStream, PktPMD* lpPktPMD);
bool RelayPacket(CSendStream& SendStream, PktDD* lpPktDD);
bool Parse(CSendStream& SendStream, PktBase* lpPktBase)
{
bool bResult = false;
PktDD* lpPktDD = static_cast<PktDD*>(lpPktBase);
switch (lpPktDD->m_wCmd)
{
case PktDD::SCmdCreateParty: bResult = CreateParty(SendStream, static_cast<PktCPD*>(lpPktDD)); break; // 파티 생성
case PktDD::SCmdDeleteParty: bResult = DeleteParty(SendStream, static_cast<PktDPD*>(lpPktDD)); break; // 파티 삭제
case PktDD::SCmdGetPartyInfo: bResult = GetPartyInfo(SendStream, static_cast<PktPID*>(lpPktDD)); break; // 파티 정보 얻기
case PktDD::SCmdTransferLeader: bResult = TransferLeader(SendStream, static_cast<PktPMD*>(lpPktDD)); break; // 파피 리더 양도
case PktDD::SCmdInsertPartyMem: bResult = InsertPartyMember(SendStream, static_cast<PktPMD*>(lpPktDD)); break; // 파티 멤버 추가
case PktDD::SCmdDeletePartyMem: bResult = DeletePartyMember(SendStream, static_cast<PktPMD*>(lpPktDD)); break; // 파티 멤버 삭제
case PktDD::SCmdDeadPartyMem:
case PktDD::SCmdMoveZonePartyMem:
case PktDD::SCmdLevelUpPartyMem:
case PktDD::SCmdChangeClassPartyMem:
case PktDD::SCmdChangeGuildPartyMem:
bResult = RelayPacket(SendStream, lpPktDD);
break;
case PktDD::SCmdAutoRoutingOn: bResult = AutoRoutingOn(SendStream, static_cast<PktPMD*>(lpPktDD)); break; // 파티 오토루팅 켜기
case PktDD::SCmdAutoRoutingOff: bResult = AutoRoutingOff(SendStream, static_cast<PktPMD*>(lpPktDD)); break; // 파티 오토루팅 끄기
default:
bResult = true;
ERRLOG1(g_Log, "파티 로그 : Cmd:0x%02x 알 수 없는 파티 명령임", lpPktDD->m_wCmd);
break;
}
if(!bResult)
{
ERRLOG1(g_Log, "파티 로그 : Cmd:0x%02x 명령 처리 실패.", lpPktDD->m_wCmd);
}
return true;
}
bool CreateParty(CSendStream& SendStream, PktCPD* lpPktCPD)
{
// 파티 생성
CPartyDBInfo* lpParty = CPartyDBMgr::GetInstance().CreateParty(CDBSingleObject::GetInstance(), lpPktCPD->m_dwLeaderID, lpPktCPD->m_cLeaderLevel,
lpPktCPD->m_wLeaderClass, lpPktCPD->m_dwLeaderGID, lpPktCPD->m_dwMemberID, lpPktCPD->m_cMemberLevel, lpPktCPD->m_wMemberClass, lpPktCPD->m_dwMemberGID);
char* lpBuffer = 0;
if (0 == lpParty)
{
ERRLOG2(g_Log, "파티 로그 : LeaderCID:%10u / MemberCID:%10u / 파티 생성 실패 : 파티 생성 실패",
lpPktCPD->m_dwLeaderID, lpPktCPD->m_dwMemberID);
}
else
{
PktCPDAck sPktCPDAck;
memset(&sPktCPDAck, 0, sizeof(PktCPDAck));
sPktCPDAck.m_wCmd = lpPktCPD->m_wCmd;
sPktCPDAck.m_Party = lpParty->GetParty();
sPktCPDAck.m_dwLeaderID = lpPktCPD->m_dwLeaderID;
sPktCPDAck.m_dwMemberID = lpPktCPD->m_dwMemberID;
sPktCPDAck.m_dwLeaderGID = lpPktCPD->m_dwLeaderGID;
sPktCPDAck.m_wLeaderClass = lpPktCPD->m_wLeaderClass;
sPktCPDAck.m_cLeaderLevel = lpPktCPD->m_cLeaderLevel;
sPktCPDAck.m_dwMemberGID = lpPktCPD->m_dwMemberGID;
sPktCPDAck.m_wMemberClass = lpPktCPD->m_wMemberClass;
sPktCPDAck.m_cMemberLevel = lpPktCPD->m_cMemberLevel;
// 캐릭터 정보 업데이트 //
lpParty->SetUserInfoLevel(lpPktCPD->m_dwLeaderID, lpPktCPD->m_cLeaderLevel);
lpParty->SetUserInfoClass(lpPktCPD->m_dwLeaderID, lpPktCPD->m_wLeaderClass);
lpParty->SetUserInfoGID(lpPktCPD->m_dwLeaderID, lpPktCPD->m_dwLeaderGID);
lpParty->SetUserInfoLevel(lpPktCPD->m_dwMemberID, lpPktCPD->m_cMemberLevel);
lpParty->SetUserInfoClass(lpPktCPD->m_dwMemberID, lpPktCPD->m_wMemberClass);
lpParty->SetUserInfoGID(lpPktCPD->m_dwMemberID, lpPktCPD->m_dwMemberGID);
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&sPktCPDAck), sizeof(PktCPDAck), CmdAgentParty, 0, 0))
{
// 게임 서버로 브로드캐스팅 //
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&sPktCPDAck), sizeof(PktCPDAck), CmdAgentParty));
return true;
}
}
return false;
}
bool DeleteParty(CSendStream& SendStream, PktDPD* lpPktDPD)
{
// 파티 삭제
if (!CPartyDBMgr::GetInstance().DestoryParty(
CDBSingleObject::GetInstance(), lpPktDPD->m_dwPartyID))
{
ERRLOG1(g_Log, "파티 로그 : PID:%10u / 파티 삭제 실패", lpPktDPD->m_dwPartyID);
}
return true;
}
bool GetPartyInfo(CSendStream& SendStream, PktPID* lpPktPID)
{
unsigned long dwPID = lpPktPID->m_dwPartyID;
unsigned long dwCID = lpPktPID->m_dwCharID;
// 파티 열기
CPartyDBInfo* lpParty = CPartyDBMgr::GetInstance().OpenParty(
CDBSingleObject::GetInstance(), dwPID);
if (0 == lpParty)
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 파티 정보 얻기 실패 : 파티 얻기 실패",
dwPID, dwCID);
}
else
{
unsigned long dwServerID = 0;
using namespace DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwCID);
if(0 != lpSessionData)
{
dwServerID = lpSessionData->GetServerID();
}
// lpParty->PartyMemAllLogout();
// lpParty->PartyMemLogin(dwCID, dwSID);
// lpParty->SetLeader(dwCID);
DETLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 파티 정보 얻기", dwPID, dwCID);
// 패킷 보내기
PktPIDAck pktPIDAck;
memset(&pktPIDAck, 0, sizeof(PktPIDAck));
pktPIDAck.m_wCmd = lpPktPID->m_wCmd;
pktPIDAck.m_Party = lpParty->GetParty();
pktPIDAck.m_dwCharID = lpPktPID->m_dwCharID;
pktPIDAck.m_dwGID = lpPktPID->m_dwGID;
pktPIDAck.m_wClass = lpPktPID->m_wClass;
pktPIDAck.m_cLevel = lpPktPID->m_cLevel;
pktPIDAck.m_dwServerID = lpPktPID->m_dwServerID;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktPIDAck),
sizeof(PktPIDAck), CmdAgentParty, 0, 0))
{
// 게임 서버로 브로드캐스팅 //
CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktPIDAck), sizeof(PktPIDAck), CmdAgentParty));
return true;
}
}
return true;
}
bool TransferLeader(CSendStream& SendStream, PktPMD* lpPktPMD)
{
unsigned long dwPartyID = lpPktPMD->m_dwPartyID;
unsigned long dwSenderID = lpPktPMD->m_dwSenderID;
unsigned long dwReferenceID = lpPktPMD->m_dwGID;
using namespace DataStorage;
CSessionData* lpSessionData = CSessionDataMgr::GetInstance().GetCharLoadedSession(dwSenderID);
CCharacterData* lpCharacterData = 0;
CPartyDBInfo* lpParty = 0;
if(0 == lpSessionData)
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 리더 이양 실패 : 캐릭터 찾기 실패",
dwPartyID, dwSenderID);
}
else if(0 == (lpCharacterData = lpSessionData->GetCharacterData()))
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 리더 이양 실패 : 캐릭터 데이터 없음",
dwPartyID, dwSenderID);
}
else if(0 == (lpParty = CPartyDBMgr::GetInstance().FindPartyMap(dwPartyID)))
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 리더 이양 실패 : 파티 찾기 실패",
dwPartyID, dwSenderID);
}
else if(!lpParty->TransferLeader(dwReferenceID, dwSenderID))
{
ERRLOG3(g_Log, "파티 로그 : PID:%10u / OldLeaderCID:%10u / NewLeaderCID:%10u / 리더 이양 실패",
dwPartyID, dwReferenceID, dwSenderID);
}
else
{
DETLOG3(g_Log, "파티 로그 : PID:%10u / OldLeaderCID:%10u / NewLeaderCID:%10u / 리더 이양 성공",
dwPartyID, dwReferenceID, dwSenderID);
SendPacket::PartyCmd(PktDD::SCmdTransferLeader, lpParty->GetPID(), dwSenderID, 0, 0,
lpSessionData->GetServerID(), 0, lpCharacterData->GetName());
}
return true;
}
bool InsertPartyMember(CSendStream& SendStream, PktPMD* lpPktPMD)
{
unsigned long dwPartyID = lpPktPMD->m_dwPartyID;
unsigned long dwSenderID = lpPktPMD->m_dwSenderID;
unsigned long dwGID = lpPktPMD->m_dwGID;
unsigned short wClass = lpPktPMD->m_wClass;
char cLevel = lpPktPMD->m_cLevel;
// 파티원 추가
if (!CPartyDBMgr::GetInstance().InsertPartyMember(
CDBSingleObject::GetInstance(), dwPartyID, dwSenderID, dwGID, wClass, cLevel))
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 파티 멤버 추가 실패", dwPartyID, dwSenderID);
}
CPartyDBInfo* lpParty = CPartyDBMgr::GetInstance().OpenParty(CDBSingleObject::GetInstance(), dwPartyID);
if(lpParty)
{
// 캐릭터 정보 업데이트 //
lpParty->SetUserInfoLevel(dwSenderID, cLevel);
lpParty->SetUserInfoClass(dwSenderID, wClass);
lpParty->SetUserInfoGID(dwSenderID, dwGID);
}
return true;
}
bool DeletePartyMember(CSendStream& SendStream, PktPMD* lpPktPMD)
{
unsigned long dwPartyID = lpPktPMD->m_dwPartyID;
unsigned long dwSenderID = lpPktPMD->m_dwSenderID;
unsigned long dwReferenceID = lpPktPMD->m_dwGID;
// 킥의 경우
if (dwSenderID != dwReferenceID)
{
dwReferenceID = 0;
}
CPartyDBInfo* lpParty = CPartyDBMgr::GetInstance().OpenParty(CDBSingleObject::GetInstance(), dwPartyID);
if(lpParty)
{
// 캐릭터 정보 업데이트 //
lpParty->SetUserInfoLevel(dwSenderID, 0);
lpParty->SetUserInfoClass(dwSenderID, 0);
lpParty->SetUserInfoGID(dwSenderID, 0);
}
// 파티원 삭제
if (!CPartyDBMgr::GetInstance().DeletePartyMember(
CDBSingleObject::GetInstance(), dwPartyID, dwSenderID, dwReferenceID))
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 파티 멤버 삭제 실패", dwPartyID, dwSenderID);
}
return true;
}
bool AutoRoutingOn(CSendStream& SendStream, PktPMD* lpPktPMD)
{
unsigned long dwPartyID = lpPktPMD->m_dwPartyID;
unsigned long dwSenderID = lpPktPMD->m_dwSenderID;
unsigned long dwReferenceID = lpPktPMD->m_dwGID;
// 오토루팅 켜기
if (!CPartyDBMgr::GetInstance().AutoRoutingOn(
CDBSingleObject::GetInstance(), dwPartyID, dwSenderID))
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 캐릭터의 오토루팅 켜기 실패 (CID 가 0이면 ALL)",
dwPartyID, dwSenderID);
}
return true;
}
bool AutoRoutingOff(CSendStream& SendStream, PktPMD* lpPktPMD)
{
unsigned long dwPartyID = lpPktPMD->m_dwPartyID;
unsigned long dwSenderID = lpPktPMD->m_dwSenderID;
unsigned long dwReferenceID = lpPktPMD->m_dwGID;
// 오토루팅 끄기
if (!CPartyDBMgr::GetInstance().AutoRoutingOff(
CDBSingleObject::GetInstance(), dwPartyID, dwSenderID))
{
ERRLOG2(g_Log, "파티 로그 : PID:%10u / CID:%10u / 캐릭터의 오토루팅 끄기 실패 (CID 가 0이면 ALL)",
dwPartyID, dwSenderID);
}
return true;
}
bool RelayPacket(CSendStream& SendStream, PktDD* lpPktDD)
{
unsigned short usPacketSize = lpPktDD->GetLen();
switch(lpPktDD->m_wCmd)
{
case PktDD::SCmdLevelUpPartyMem:
case PktDD::SCmdChangeClassPartyMem:
case PktDD::SCmdChangeGuildPartyMem:
{
PktPMD* lpPktPMD = static_cast<PktPMD*>(lpPktDD);
CPartyDBInfo* lpParty = CPartyDBMgr::GetInstance().OpenParty(CDBSingleObject::GetInstance(), lpPktPMD->m_dwPartyID);
if(lpParty)
{
// 캐릭터 정보 업데이트 //
if(PktDD::SCmdLevelUpPartyMem)
{
lpParty->SetUserInfoLevel(lpPktPMD->m_dwSenderID, lpPktPMD->m_cLevel);
}
if(PktDD::SCmdChangeClassPartyMem)
{
lpParty->SetUserInfoClass(lpPktPMD->m_dwSenderID, lpPktPMD->m_wClass);
}
if(PktDD::SCmdChangeGuildPartyMem)
{
lpParty->SetUserInfoGID(lpPktPMD->m_dwSenderID, lpPktPMD->m_dwGID);
}
}
}
break;
}
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(lpPktDD),
usPacketSize, CmdAgentParty, 0, 0))
{
CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(lpPktDD), usPacketSize, CmdAgentParty));
}
return true;
}
}
}

View File

@@ -0,0 +1,17 @@
#ifndef _DBAGENT_SERVER_PARSE_PARTY_H_
#define _DBAGENT_SERVER_PARSE_PARTY_H_
// forward delc.
class CSendStream;
struct PktBase;
namespace DBAgent
{
namespace ParseParty
{
bool Parse(CSendStream& SendStream, PktBase* lpPktBase);
}
}
#endif

View File

@@ -0,0 +1,244 @@
#include "stdafx.h"
#include "SendAdminTool.h"
#include <Network/Packet/PacketStruct/CharAdminPacket.h>
#include <Network/Packet/PacketStruct/GameEventPacket.h>
#include <Network/Packet/PacketStruct/CharLoginOutPacketStruct.h>
#include <Network/Dispatch/AdminToolDispatch.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Utility/Setup/ServerSetup.h>
#include <DataStorage/StoreData.h>
#include <DataStorage/CharacterData.h>
#include <Log/ServerLog.h>
namespace DBAgent
{
namespace SendPacket
{
bool ItemQtyCheck(unsigned long dwItemTypeID, unsigned long dwItemQty,
unsigned long dwCurrentItemQty, time_t tStartTime, time_t tEndTime,
unsigned char cType, unsigned short usError)
{
PktItemQtyControl pktItemQtyControl;
memset(&pktItemQtyControl, 0, sizeof(PktItemQtyControl));
pktItemQtyControl.m_dwItemTypeID = dwItemTypeID;
pktItemQtyControl.m_dwItemQty = dwItemQty;
pktItemQtyControl.m_dwCurrentItemQty = dwCurrentItemQty;
pktItemQtyControl.m_tStartTime = tStartTime;
pktItemQtyControl.m_tEndTime = tEndTime;
pktItemQtyControl.m_cType = cType;
pktItemQtyControl.m_cGroup = CServerSetup::GetInstance().GetServerGroup();
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktItemQtyControl),
sizeof(PktItemQtyControl), CmdItemQtyCheck, 0, usError))
{
DBAgent::CAdminToolDispatch::GetDispatchTable().Process(
CSendPacketAllServer(reinterpret_cast<char*>(&pktItemQtyControl),
sizeof(PktItemQtyControl), CmdItemQtyCheck));
return true;
}
return false;
}
bool AdminToolGetDataAck(CSendStream& SendStream, PktAdminToolGetData::GetDataType dataType,
unsigned long dwRequestKey, unsigned long dwUID, unsigned long dwCID,
const char* lpData, unsigned long dwDataSize, unsigned short usError,
unsigned char cOldServerGroupID)
{
// 최대 패킷 크기보다 크면 에러
if(sizeof(PktAdminToolGetDataAck) + dwDataSize <= MAX_PACKET_LEN)
{
char szPacket[PktMaxLen];
PktAdminToolGetDataAck* lpPktAdminToolGetDataAck =
reinterpret_cast<PktAdminToolGetDataAck*>(szPacket);
lpPktAdminToolGetDataAck->m_dwRequestKey = dwRequestKey;
lpPktAdminToolGetDataAck->m_dwUID = dwUID;
lpPktAdminToolGetDataAck->m_dwCID = dwCID;
lpPktAdminToolGetDataAck->m_cType = dataType;
lpPktAdminToolGetDataAck->m_cOldServerGroupID = cOldServerGroupID; // Part2Selectable 타입에서 필요.
if(0 != lpData && 0 < dwDataSize)
{
memcpy(lpPktAdminToolGetDataAck + 1, lpData, dwDataSize);
}
else
{
dwDataSize = 0;
}
return SendStream.WrapCompress(szPacket,
static_cast<unsigned short>(sizeof(PktAdminToolGetDataAck) + dwDataSize),
CmdAdminToolGetData, 0, usError);
}
ERRLOG4(g_Log, "UID:%10u / CID:%10u / dwSize:%u / DataType:%d "
"운영툴에 데이터 전송 실패 : 데이터 + 헤더 크기가 최대 패킷 크기 이상입니다",
dwUID, dwCID, dwDataSize, dataType);
return false;
}
bool AdminToolSetDataAck(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
unsigned char cType, unsigned short eErrorCode)
{
PktNewAdminToolSetDataAck* lpSetDataAck = reinterpret_cast<PktNewAdminToolSetDataAck*>(
SendStream.GetBuffer(sizeof(PktNewAdminToolSetDataAck)));
if(0 != lpSetDataAck)
{
lpSetDataAck->m_dwRequestKey = dwRequestKey;
lpSetDataAck->m_dwUID = dwUID;
lpSetDataAck->m_dwCID = dwCID;
lpSetDataAck->m_cType = cType;
return SendStream.WrapHeader(sizeof(PktNewAdminToolSetDataAck),
CmdAdminToolSetData, 0, eErrorCode);
}
return false;
}
inline void CopyAndAdvanceDst(char*& lpWritePos, const void* lpData, unsigned long dwSize)
{
memcpy(lpWritePos, lpData, dwSize);
lpWritePos += dwSize;
}
// 캐릭터 데이터를 운영툴로 전송한다.
bool TotalDataToAdminTool(CSendStream& SendStream, unsigned long dwRequestKey, IN_ADDR peerAddr,
DataStorage::CStoreData& storeData, DataStorage::CCharacterData& characterData)
{
unsigned long dwUID = storeData.GetUID();
unsigned long dwCID = characterData.GetCID();
const unsigned long MAX_CHAR_DATA_SIZE = DBUpdateData::MAX_DBUPDATE_SIZE +
sizeof(unsigned short) * DBUpdateData::MAX_UPDATE_DB;
const unsigned long MAX_CHAR_EXTRA_DATA_SIZE = sizeof(CHAR_INFOEX) +
sizeof(QUEST) + sizeof(HISTORY) + sizeof(CONFIG) + sizeof(STORE_INFO);
const unsigned long MAX_FRIEND_BAN_DATA_SIZE =
std::max(CFriendList::MAX_FRIENDS_NUM * sizeof(FriendInfo),
CBanList::MAX_BAN_NUM * sizeof(BanInfo));
const unsigned long MAX_ADMIN_TOOL_DATA_SIZE = std::max(
std::max(MAX_CHAR_DATA_SIZE, MAX_CHAR_EXTRA_DATA_SIZE), MAX_FRIEND_BAN_DATA_SIZE);
char* szDataBuffer = new char[MAX_ADMIN_TOOL_DATA_SIZE];
if(0 == szDataBuffer)
{
return false;
}
const int MAX_ADDR_LEN = 32;
char szAdminToolAddr[MAX_ADDR_LEN];
_snprintf(szAdminToolAddr, MAX_ADDR_LEN - 1, "%s", inet_ntoa(peerAddr));
szAdminToolAddr[MAX_ADDR_LEN - 1] = 0;
// ------------------------------------------------------------------------------------------
// CHAR_BASIC_DATA 전송
unsigned long dwCharDataWritten = MAX_ADMIN_TOOL_DATA_SIZE -
sizeof(unsigned short) * DBUpdateData::MAX_UPDATE_DB;
char* szCharData = szDataBuffer + sizeof(unsigned short) * DBUpdateData::MAX_UPDATE_DB;
unsigned short* usSizeArray = reinterpret_cast<unsigned short*>(szDataBuffer);
if(characterData.SerializeOut(szCharData, usSizeArray,
dwCharDataWritten, DBUpdateData::MAX_UPDATE_DB))
{
dwCharDataWritten += sizeof(unsigned short) * DBUpdateData::MAX_UPDATE_DB;
if(SendPacket::AdminToolGetDataAck(SendStream, PktAdminToolGetData::CHAR_BASIC_DATA,
dwRequestKey, dwUID, dwCID, szDataBuffer, dwCharDataWritten, 0))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴로 CHAR_BASIC_DATA 전송 성공", dwUID, dwCID, szAdminToolAddr);
}
}
// ------------------------------------------------------------------------------------------
// CHAR_EXTRA_DATA 전송
char* szExtraDataPos = szDataBuffer;
CopyAndAdvanceDst(szExtraDataPos, &characterData.GetInfoEx(), sizeof(CHAR_INFOEX));
CopyAndAdvanceDst(szExtraDataPos, &characterData.GetQuest(), sizeof(QUEST));
CopyAndAdvanceDst(szExtraDataPos, &characterData.GetHistory(), sizeof(HISTORY));
CopyAndAdvanceDst(szExtraDataPos, &characterData.GetConfig(), sizeof(CONFIG));
CopyAndAdvanceDst(szExtraDataPos, &storeData.GetStoreInfo(), sizeof(STORE_INFO));
if(SendPacket::AdminToolGetDataAck(SendStream,
PktAdminToolGetData::CHAR_EXTRA_DATA, dwRequestKey, dwUID, dwCID, szDataBuffer,
static_cast<unsigned long>(szExtraDataPos - szDataBuffer), 0))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴로 CHAR_EXTRA_DATA 전송 성공", dwUID, dwCID, szAdminToolAddr);
}
// ---------------------------------------------------------------------------------------------
// CHAR_FRIEND_DATA
// CHAR_BAN_DATA
unsigned long dwFriendBanWritten = MAX_FRIEND_BAN_DATA_SIZE;
if(characterData.GetFriendList().SerializeOut(szDataBuffer, dwFriendBanWritten))
{
if(SendPacket::AdminToolGetDataAck(SendStream, PktAdminToolGetData::CHAR_FRIEND_DATA,
dwRequestKey, dwUID, dwCID, szDataBuffer, dwFriendBanWritten, 0))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴로 CHAR_FRIEND_DATA 전송 성공", dwUID, dwCID, szAdminToolAddr);
}
}
dwFriendBanWritten = MAX_FRIEND_BAN_DATA_SIZE;
if(characterData.GetBanList().SerializeOut(szDataBuffer, dwFriendBanWritten))
{
if(SendPacket::AdminToolGetDataAck(SendStream, PktAdminToolGetData::CHAR_BAN_DATA,
dwRequestKey, dwUID, dwCID, szDataBuffer, dwFriendBanWritten, 0))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴로 CHAR_BAN_DATA 전송 성공", dwUID, dwCID, szAdminToolAddr);
}
}
// ---------------------------------------------------------------------------------------------
// STORE_12_DATA
if(SendPacket::AdminToolGetDataAck(SendStream, PktAdminToolGetData::STORE_12_DATA,
dwRequestKey, dwUID, dwCID, reinterpret_cast<const char*>(&storeData.GetStore1()), sizeof(STORE), 0))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴로 STORE_12_DATA 전송 성공", dwUID, dwCID, szAdminToolAddr);
}
// ---------------------------------------------------------------------------------------------
// STORE_34_DATA
if(SendPacket::AdminToolGetDataAck(SendStream, PktAdminToolGetData::STORE_34_DATA,
dwRequestKey, dwUID, dwCID, reinterpret_cast<const char*>(&storeData.GetStore2()), sizeof(STORE), 0))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / IP:%15s / 운영툴로 STORE_34_DATA 전송 성공", dwUID, dwCID, szAdminToolAddr);
}
delete [] szDataBuffer;
return true;
}
}
}

View File

@@ -0,0 +1,42 @@
#ifndef _DBAGENT_SERVER_SEND_ADMIN_TOOL_H_
#define _DBAGENT_SERVER_SEND_ADMIN_TOOL_H_
#include <ctime>
#include <Network/Packet/PacketStruct/CharAdminPacket.h>
// forward decl.
class CSendStream;
namespace DBAgent
{
namespace DataStorage
{
// forward decl.
class CStoreData;
class CCharacterData;
}
namespace SendPacket
{
bool ItemQtyCheck(unsigned long dwItemTypeID, unsigned long dwItemQty,
unsigned long dwCurrentItemQty, time_t tStartTime, time_t tEndTime,
unsigned char cType, unsigned short usError = 0);
bool AdminToolGetDataAck(CSendStream& SendStream, PktAdminToolGetData::GetDataType dataType,
unsigned long dwRequestKey, unsigned long dwUID, unsigned long dwCID,
const char* lpData, unsigned long dwDataSize, unsigned short usError,
unsigned char cOldServerGroupID = 0);
bool AdminToolSetDataAck(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID, unsigned char cType, unsigned short eErrorCode);
bool TotalDataToAdminTool(CSendStream& SendStream, unsigned long dwRequestKey, IN_ADDR peerAddr,
DataStorage::CStoreData& storeData, DataStorage::CCharacterData& characterData);
}
}
#endif

View File

@@ -0,0 +1,331 @@
#include "stdafx.h"
#include "SendCharManage.h"
#include <Network/Stream/SendStream.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/AuthServerToDBAgentServer.h>
#include <Network/Packet/PacketStruct/UnifiedCharPacket.h>
#include <Network/Packet/PacketStruct/CharItemPacket.h>
#include <Network/Packet/PacketStruct/CharStatusPacket.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Utility/Setup/ServerSetup.h>
#include <DB/DBdefine.h>
namespace DBAgent
{
namespace SendPacket
{
// WORK_LIST 2.1 계정 국적 추가
// 캐릭터 뷰 얻어오기
bool UserLogin(CSendStream& SendStream, unsigned long dwRequestKey, unsigned long dwUID,
const CHAR_VIEW* lpCharView, const sGuildData* lpGuildData, const STORE_INFO* pStoreInfo, unsigned long dwCharViewNum,
unsigned char cAccountNation, int nPlayTime, unsigned char cAdminLevel, unsigned char cBillingUser,
unsigned char cBillingType, unsigned char cLoginType, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktULDAck));
if(0 != lpBuffer)
{
PktULDAck* lpPktULDAck = reinterpret_cast<PktULDAck*>(lpBuffer);
lpPktULDAck->m_dwRequestKey = dwRequestKey;
lpPktULDAck->m_wCmd = PktDD::SCmdUserLogin;
lpPktULDAck->m_nPlayTime = nPlayTime;
lpPktULDAck->m_usAdminLevel = cAdminLevel;
lpPktULDAck->m_cBillingUser = cBillingUser;
lpPktULDAck->m_cBillingType = cBillingType;
lpPktULDAck->m_cLoginType = cLoginType;
lpPktULDAck->m_dwUserID = dwUID;
// WORK_LIST 2.1 계정 국적 추가
lpPktULDAck->m_cAccountNation = cAccountNation;
memset(lpPktULDAck->m_CharView, 0, sizeof(CHAR_VIEW) * PktULDAck::MAX_CHAR_VIEW);
memset(lpPktULDAck->m_GuildData, 0, sizeof(sGuildData) * PktULDAck::MAX_CHAR_VIEW);
memset(&lpPktULDAck->m_sStoreInfo, 0, sizeof(STORE_INFO));
if(0 != lpCharView && 0 != dwCharViewNum)
{
memcpy(lpPktULDAck->m_CharView, lpCharView,
sizeof(CHAR_VIEW) * std::min(unsigned long(PktULDAck::MAX_CHAR_VIEW), dwCharViewNum));
memcpy(lpPktULDAck->m_GuildData, lpGuildData, sizeof(sGuildData) * PktULDAck::MAX_CHAR_VIEW);
memcpy(&lpPktULDAck->m_sStoreInfo, pStoreInfo, sizeof(STORE_INFO));
}
return SendStream.WrapHeader(sizeof(PktULDAck), CmdDBGetData, 0, usError);
}
return false;
}
// 캐릭터 선택.
bool CharSelect(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktCSDAck));
if(0 != lpBuffer)
{
PktCSDAck* lpPktCSDAck = reinterpret_cast<PktCSDAck*>(lpBuffer);
lpPktCSDAck->m_dwRequestKey = dwRequestKey;
lpPktCSDAck->m_wCmd = PktDD::SCmdCharSelect;
lpPktCSDAck->m_cZone = cZone;
CUserPercentageInZone userPercentageInZone(
lpPktCSDAck->m_wChannelNum, cZone, PktCSDAck::MAX_CHANNEL_NUM);
CGameDispatch::GetDispatchTable().Process(userPercentageInZone);
return SendStream.WrapHeader(sizeof(PktCSDAck), CmdDBGetData, 0, usError);
}
return false;
}
bool CharCreate(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwCID, unsigned long dwSlot,
const CHAR_VIEW& CharView, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktCCDAck));
if(0 != lpBuffer)
{
PktCCDAck* lpPktCCDAck = reinterpret_cast<PktCCDAck*>(lpBuffer);
lpPktCCDAck->m_dwRequestKey = dwRequestKey;
lpPktCCDAck->m_wCmd = PktDD::SCmdCharCreate;
lpPktCCDAck->m_dwCharID = dwCID;
lpPktCCDAck->m_dwSlot = dwSlot;
lpPktCCDAck->m_CharView = CharView;
return SendStream.WrapHeader(sizeof(PktCCDAck), CmdDBGetData, 0, usError);
}
return false;
}
bool CharDelete(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwSlot,
unsigned long dwCID, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktCDD));
if(0 != lpBuffer)
{
PktCDD* lpPktCDDAck = reinterpret_cast<PktCDD*>(lpBuffer);
lpPktCDDAck->m_dwRequestKey = dwRequestKey;
lpPktCDDAck->m_wCmd = PktDD::SCmdCharDelete;
lpPktCDDAck->m_dwUserID = dwUID;
lpPktCDDAck->m_dwSlotNum = dwSlot;
lpPktCDDAck->m_dwCharID = dwCID;
return SendStream.WrapHeader(sizeof(PktCDD), CmdDBGetData, 0, usError);
}
return false;
}
// WORK_LIST 2.1 계정 국적 추가
bool SelectAccountNation(CSendStream& SendStream, unsigned long dwRequestKey, unsigned long dwUID,
unsigned char cType, unsigned char cAccountNation, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSAND));
if (0 != lpBuffer)
{
PktSAND* lpPktSANDAck = reinterpret_cast<PktSAND*>(lpBuffer);
lpPktSANDAck->m_dwRequestKey = dwRequestKey;
lpPktSANDAck->m_wCmd = PktDD::SCmdSelectNation;
lpPktSANDAck->m_dwUserID = dwUID;
lpPktSANDAck->m_cType = cType;
lpPktSANDAck->m_cAccountNation = cAccountNation;
return SendStream.WrapHeader(sizeof(PktSAND), CmdDBGetData, 0, usError);
}
return false;
}
// WORK_LIST 2.3 계정 국적 변경 기능 구현
bool NationChangeResult(CSendStream& SendStream, unsigned long dwRequestKey, unsigned long dwUID,
unsigned long* aryGID, unsigned long* aryFame)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktANCAck));
if (0 != lpBuffer)
{
PktANCAck* lpPktANCAck = reinterpret_cast<PktANCAck*>(lpBuffer);
lpPktANCAck->m_dwRequestKey = dwRequestKey;
lpPktANCAck->m_wCmd = PktDD::SCmdNationChangeResult;
lpPktANCAck->m_dwUserID = dwUID;
::memcpy(lpPktANCAck->m_dwGID, aryGID, sizeof(unsigned long) * PktANCAck::MAX_CHAR_VIEW);
::memcpy(lpPktANCAck->m_dwFame, aryFame, sizeof(unsigned long) * PktANCAck::MAX_CHAR_VIEW);
return SendStream.WrapHeader(sizeof(PktANCAck), CmdDBGetData, 0, 0);
}
return false;
}
bool UnifiedCharInfo(CSendStream& SendStream, unsigned long dwUID,
unsigned char cTransferedCharCount, const USER_INFO& userInfo,
const UnifiedStoreInfo* lpUnifiedStoreInfo, unsigned long dwUnifiedStoreNum,
const UnifiedCharData* lpUnifiedCharData, unsigned long dwUnifiedCharNum)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktUnifiedCharInfo));
if (0 != lpBuffer)
{
PktUnifiedCharInfo* lpPktUnifiedCharInfo =
reinterpret_cast<PktUnifiedCharInfo*>(lpBuffer);
lpPktUnifiedCharInfo->dwUID = dwUID;
unsigned long dwMinUnifiedStoreNum =
std::min(unsigned long(PktUnifiedCharInfo::MAX_STORE_INFO), dwUnifiedStoreNum);
unsigned long dwMinUnifiedCharNum =
std::min(unsigned long(PktUnifiedCharInfo::MAX_CHAR_DATA), dwUnifiedCharNum);
lpPktUnifiedCharInfo->cRestrictedPart1ToPart2Level =
CServerSetup::GetInstance().GetRestrictedPart1ToPart2Level();
unsigned char cMaxTransferCount = CServerSetup::GetInstance().GetMaxTransferPart1ToPart2Count();
if (cTransferedCharCount <= cMaxTransferCount)
{
lpPktUnifiedCharInfo->cRemainCharTransferCount = cMaxTransferCount - cTransferedCharCount;
}
else
{
lpPktUnifiedCharInfo->cRemainCharTransferCount = 0;
}
lpPktUnifiedCharInfo->userInfo = userInfo;
memcpy(lpPktUnifiedCharInfo->unifiedStoreInfo, lpUnifiedStoreInfo,
sizeof(UnifiedStoreInfo) * dwMinUnifiedStoreNum);
memcpy(lpPktUnifiedCharInfo->unifiedCharData, lpUnifiedCharData,
sizeof(UnifiedCharData) * dwMinUnifiedCharNum);
lpPktUnifiedCharInfo->cStoreInfoNum = static_cast<unsigned char>(dwMinUnifiedStoreNum);
lpPktUnifiedCharInfo->cCharDataNum = static_cast<unsigned char>(dwMinUnifiedCharNum);
return SendStream.WrapHeader(sizeof(PktUnifiedCharInfo), CmdUnifiedCharInfo, 0, 0);
}
return false;
}
bool UnifiedCharSelectReq(CSendStream& SendStream, unsigned long dwUID,
unsigned long dwRequestKey, unsigned long* lpdwCID, unsigned long dwCIDNum,
unsigned char cSelectedStoreServerGroup, unsigned char cSelectedNation)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktUnifiedCharSelectReq));
if (0 != lpBuffer)
{
PktUnifiedCharSelectReq* lpPktUnifiedCharSelectReq =
reinterpret_cast<PktUnifiedCharSelectReq*>(lpBuffer);
memset(lpPktUnifiedCharSelectReq->szPassword,
0, sizeof(char) * PktUnifiedCharSelectReq::MAX_PASSWORD_LEN);
lpPktUnifiedCharSelectReq->dwUID= dwUID;
lpPktUnifiedCharSelectReq->dwRequestKey = dwRequestKey;
memcpy(lpPktUnifiedCharSelectReq->dwCID, lpdwCID,
sizeof(unsigned long) * min(long(USER_INFO::MAX_CHAR_NUM), long(dwCIDNum)));
lpPktUnifiedCharSelectReq->cSelectedServerGroupID = cSelectedStoreServerGroup;
lpPktUnifiedCharSelectReq->cSelectedNation = cSelectedNation;
return SendStream.WrapHeader(sizeof(PktUnifiedCharSelectReq), CmdUnifiedCharSelect, 0, 0);
}
return false;
}
bool UnifiedCharSelectAck(CSendStream& SendStream, unsigned long dwUID,
unsigned long dwRequestKey, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktUnifiedCharSelectAck));
if (0 != lpBuffer)
{
PktUnifiedCharSelectAck* lpPktUnifiedCharSelectAck =
reinterpret_cast<PktUnifiedCharSelectAck*>(lpBuffer);
lpPktUnifiedCharSelectAck->dwUID = dwUID;
lpPktUnifiedCharSelectAck->dwRequestKey = dwRequestKey;
return SendStream.WrapHeader(sizeof(PktUnifiedCharSelectAck),
CmdUnifiedCharSelect, 0, usError);
}
return false;
}
bool CharUseCashItem(CSendStream& SendStream, unsigned long dwSender, unsigned long dwReceiver,
Item::ItemPos itemPos, unsigned char cRemainItemNum, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktUI));
if (NULL != lpBuffer)
{
PktUI* lpPktUI = reinterpret_cast<PktUI*>(lpBuffer);
lpPktUI->m_dwSender = dwSender;
lpPktUI->m_dwRecver = dwReceiver;
lpPktUI->m_itemPos = itemPos;
lpPktUI->m_cRemainItemNum = cRemainItemNum;
return SendStream.WrapCrypt(sizeof(PktUI), CmdCharUseCashItem, 0, usError);
}
return false;
}
bool CharExtraEvent(CSendStream& SendStream, unsigned long dwUID, unsigned long dwCID,
unsigned long dwEventID, unsigned long dwValue1, unsigned long dwValue2, unsigned short usError)
{
// edith 2009.09.05 신규 이벤트 제작부분
char* lpBuffer = SendStream.GetBuffer(sizeof(PktExtraEvent));
if (NULL != lpBuffer)
{
PktExtraEvent* lpPktEE = reinterpret_cast<PktExtraEvent*>(lpBuffer);
lpPktEE->m_dwUserID = dwUID;
lpPktEE->m_dwCharID = dwCID;
lpPktEE->m_dwEventID = dwEventID;
lpPktEE->m_dwValue1 = dwValue1;
lpPktEE->m_dwValue2 = dwValue2;
return SendStream.WrapCrypt(sizeof(PktExtraEvent), CmdExtraEvent, 0, usError);
}
return false;
}
}
}

View File

@@ -0,0 +1,83 @@
#ifndef _DBAGENT_SERVER_SEND_CHAR_MANAGE_H_
#define _DBAGENT_SERVER_SEND_CHAR_MANAGE_H_
#include <DB/DBdefine.h>
#include <Item/Item.h>
// forward decl.
class CSendStream;
struct USER_INFO;
struct CHAR_VIEW;
struct sGuildData;
struct UnifiedStoreInfo;
struct UnifiedCharData;
namespace DBAgent
{
namespace DataStorage
{
// forward delc.
class CSessionData;
}
namespace SendPacket
{
// WORK_LIST 2.1 계정 국적 추가
// 캐릭터 뷰 얻어 오기
bool UserLogin(CSendStream& SendStream, unsigned long dwRequestKey, unsigned long dwUID,
const CHAR_VIEW* lpCharView, const sGuildData* lpGuildData, const STORE_INFO* pStoreInfo, unsigned long dwCharViewNum,
unsigned char cAccountNation, int nPlayTime, unsigned char cAdminLevel, unsigned char cBillingUser,
unsigned char cBillingType, unsigned char cLoginType, unsigned short usError);
// 캐릭터 선택
bool CharSelect(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned short usError);
// 캐릭터 생성
bool CharCreate(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwCID, unsigned long dwSlot, const CHAR_VIEW& CharView, unsigned short usError);
// 캐릭터 삭제
bool CharDelete(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwSlot, unsigned long dwCID, unsigned short usError);
// 아이템 생성
bool CharCreateItem(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned short usError);
// WORK_LIST 2.1 계정 국적 추가
// 계정 국적 설정 및 변경
bool SelectAccountNation(CSendStream& SendStream, unsigned long dwRequestKey, unsigned long dwUID,
unsigned char cType, unsigned char cAccountNation, unsigned short usError);
// WORK_LIST 2.3 계정 국적 변경 기능 구현
bool NationChangeResult(CSendStream& SendStream, unsigned long dwRequestKey, unsigned long dwUID,
unsigned long* aryGID, unsigned long* aryFame);
// 서버통합 캐릭터 정보 전달. 모든 캐릭터를 선택할 수 있는 통합시에는 데이터를 전달하지 않는다.
bool UnifiedCharInfo(CSendStream& SendStream,
unsigned long dwUID, unsigned char cTransferedCharCount, const USER_INFO& userInfo,
const UnifiedStoreInfo* lpUnifiedStoreInfo, unsigned long dwUnifiedStoreNum,
const UnifiedCharData* lpUnifiedCharData, unsigned long dwUnifiedCharNum);
// Part1 DB중계서버로 데이터를 전송한다.
bool UnifiedCharSelectReq(CSendStream& SendStream, unsigned long dwUID,
unsigned long dwRequestKey, unsigned long* lpdwCID, unsigned long dwCIDNum,
unsigned char cSelectedStoreServerGroup, unsigned char cSelectedNation);
// 인증서버로 캐릭터 선택 성공/실패를 준다.
bool UnifiedCharSelectAck(CSendStream& SendStream, unsigned long dwUID,
unsigned long dwRequestKey, unsigned short usError);
// 캐쉬아이템을 사용
bool CharUseCashItem(CSendStream& SendStream, unsigned long dwSender, unsigned long dwReceiver,
Item::ItemPos itemPos, unsigned char cRemainItemNum, unsigned short usError);
// 엑스트라 이벤트 전송
bool CharExtraEvent(CSendStream& SendStream, unsigned long dwUID, unsigned long dwCID,
unsigned long dwEventID, unsigned long dwValue1, unsigned long dwValue2, unsigned short usError);
}
}
#endif

View File

@@ -0,0 +1,114 @@
#include "stdafx.h"
#include "SendGuild.h"
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/GuildPacket.h>
#include <Network/Stream/SendStream.h>
#include <Network/Dispatch/GameDispatch.h>
namespace DBAgent
{
namespace SendPacket
{
bool GuildCmd(CSendStream* lpSendStream,
unsigned long dwGID, unsigned long dwSenderID, unsigned long dwReferenceID,
unsigned short wCmd, const char* szSenderName, const char* szGuildName, unsigned short wError)
{
PktGuildCmd pktGuildCmd;
memset(&pktGuildCmd, 0, sizeof(PktGuildCmd));
pktGuildCmd.m_dwGID = dwGID;
pktGuildCmd.m_dwSenderID = dwSenderID;
pktGuildCmd.m_dwReferenceID = dwReferenceID;
pktGuildCmd.m_wCmd = wCmd;
if(szSenderName)
strncpy(pktGuildCmd.m_szSenderName, szSenderName, MAX_MEMBER_NAME_LEN);
if(szGuildName)
strncpy(pktGuildCmd.m_szGuildName, szGuildName, MAX_GUILD_NAME_LEN);
if (PktBase::NO_SERVER_ERR == wError)
{
// 서버 에러가 아닌 경우 전 서버에 보낸다.
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildCmd),
sizeof(PktGuildCmd), CmdGuildCmd, 0, wError))
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktGuildCmd), sizeof(PktGuildCmd), CmdGuildCmd));
return true;
}
}
else if(0 != lpSendStream)
{
// 서버 에러인경우, 해당 서버에만 보낸다.
return lpSendStream->WrapCompress(reinterpret_cast<char*>(&pktGuildCmd),
sizeof(PktGuildCmd), CmdGuildCmd, 0, wError);
}
return false;
}
bool GuildMemberFameUpdate(unsigned long dwCID, unsigned long dwOurGID, unsigned char cType, int nAddFame, unsigned char cZone, unsigned long dwEnemyGID)
{
PktGuildMemberFameUpdate pktGuildMemberFameUpdate;
memset(&pktGuildMemberFameUpdate, 0, sizeof(PktGuildMemberFameUpdate));
pktGuildMemberFameUpdate.m_dwCID = dwCID;
pktGuildMemberFameUpdate.m_dwOurGID = dwOurGID;
pktGuildMemberFameUpdate.m_dwEnemyGID = dwEnemyGID;
pktGuildMemberFameUpdate.m_cType = cType;
pktGuildMemberFameUpdate.m_nAddFame = nAddFame;
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildMemberFameUpdate),
sizeof(PktGuildMemberFameUpdate), CmdGuildMemberFameUpdate, 0, 0))
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketToZone(
reinterpret_cast<char*>(&pktGuildMemberFameUpdate),
sizeof(PktGuildMemberFameUpdate), CmdGuildMemberFameUpdate, cZone));
return true;
}
return false;
}
bool GuildMemberGoldUpdate(unsigned long dwCID, unsigned long dwGID, unsigned long dwGold, unsigned char cZone)
{
PktGuildMemberGoldUpdate pktGuildMemberGoldUpdate;
memset(&pktGuildMemberGoldUpdate, 0, sizeof(PktGuildMemberGoldUpdate));
pktGuildMemberGoldUpdate.m_dwCID = dwCID;
pktGuildMemberGoldUpdate.m_dwGID = dwGID;
pktGuildMemberGoldUpdate.m_dwGold = dwGold;
if (PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktGuildMemberGoldUpdate),
sizeof(PktGuildMemberGoldUpdate), CmdGuildMemberGoldUpdate, 0, 0))
{
DBAgent::CGameDispatch::GetDispatchTable().Process(CSendPacketToZone(
reinterpret_cast<char*>(&pktGuildMemberGoldUpdate),
sizeof(PktGuildMemberGoldUpdate), CmdGuildMemberGoldUpdate, cZone));
return true;
}
return false;
}
/*bool KeyInfo(unsigned long dwCID)
{
PktGuildMemberGoldUpdate pktGuildMemberGoldUpdate;
memset(&pktGuildMemberGoldUpdate, 0, sizeof(PktGuildMemberGoldUpdate));
return false;
}*/
}
}

View File

@@ -0,0 +1,23 @@
#ifndef _DBAGENT_SERVER_SEND_GUILD_H_
#define _DBAGENT_SERVER_SEND_GUILD_H_
// forward decl.
class CSendStream;
namespace DBAgent
{
namespace SendPacket
{
bool GuildCmd(CSendStream* lpSendStream,
unsigned long dwGID, unsigned long dwSenderID, unsigned long dwReferenceID,
unsigned short wCmd, const char* szSenderName, const char* szGuildName, unsigned short wError);
bool GuildMemberFameUpdate(unsigned long dwCID, unsigned long dwOurGID,
unsigned char cType, int nAddFame, unsigned char cZone, unsigned long dwEnemyGID = 0);
bool GuildMemberGoldUpdate(unsigned long dwCID,
unsigned long dwGID, unsigned long dwGold, unsigned char cZone);
}
}
#endif

View File

@@ -0,0 +1,653 @@
#include "stdafx.h"
#include "SendLoginout.h"
#include <Network/Stream/SendStream.h>
#include <Network/Packet/PacketStruct/CharLoginOutPacket.h>
#include <Network/Packet/PacketStruct/CharLoginOutPacketStruct.h>
#include <Network/Packet/PacketStruct/CharItemPacket.h>
#include <Network/Packet/PacketStruct/CharQuestPacket.h>
#include <Network/Packet/PacketStruct/CharConfigPacket.h>
#include <Network/Packet/PacketStruct/AuthServerToDBAgentServer.h>
#include <DataStorage/StoreData.h>
#include <DataStorage/CharacterData.h>
#include <DataStorage/SessionData.h>
#include <Log/ServerLog.h>
#include <Network/Packet/PacketCommand.h>
#include <Community/Party/PartyDBInfo.h>
#include <Community/Party/PartyDBMgr.h>
#include <Community/Guild/GuildDB.h>
#include <Community/Guild/GuildDBMgr.h>
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <Utility/Setup/ServerSetup.h>
#include <DataStorage/SessionDataMgr.h>
#include <GameTime/GameTimeConstants.h>
#include <GameTime/GameTimeDBMgr.h>
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
namespace DBAgent
{
namespace SendPacket
{
// 친구 / 거부 데이터 전송
bool Friend(CSendStream& SendStream, unsigned char cCmd, unsigned long dwRequestKey, unsigned long dwUID, unsigned long dwCID,
unsigned long dwGID, unsigned short wClass, char cLevel, unsigned long dwServerID, const char* lpData, unsigned long dwDataLen);
// 퀘스트 / 히스토리 데이터 전송
bool Quest(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
const char* lpQuestBuffer, unsigned long dwQuestSize,
const char* lpHistoryBuffer, unsigned long dwHistorySize);
// 설정 정보 전송
bool ConfigInfo(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
const char* lpConfigBuffer, unsigned long dwConfigSize);
// 창고 정보 전송
bool DepositData(CSendStream& SendStream, unsigned char cCmd,
unsigned long dwRequestKey, unsigned long dwCID, const STORE_INFO& storeInfo);
// 창고 데이터 전송
bool DepositDBUpdate(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
unsigned char cTabNum, bool bComplete,
const STORE_INFO& storeInfo, const STORE& store);
// 세션 시작
bool StartSession(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwSessionID,
unsigned char cFirstLogin, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSSD));
if(0 != lpBuffer)
{
PktSSD* lpPktSSDAck = reinterpret_cast<PktSSD*>(lpBuffer);
lpPktSSDAck->m_dwRequestKey = dwRequestKey;
lpPktSSDAck->m_wCmd = PktDD::SCmdStartSession;
lpPktSSDAck->m_dwUserID = dwUID;
lpPktSSDAck->m_dwSessionID = dwSessionID;
lpPktSSDAck->m_cAgentServerType =
static_cast<unsigned char>(CServerSetup::GetInstance().GetAgentServerType());
lpPktSSDAck->m_cFirstLogin =
(UnifiedConst::Part2Selectable != lpPktSSDAck->m_cAgentServerType)
? cFirstLogin : static_cast<unsigned char>(CServerSetup::GetInstance().GetSelectableUnifiedServerNum());
ZeroMemory(lpPktSSDAck->m_AccountName, sizeof(char)*PktSSD::MaxName);
ZeroMemory(lpPktSSDAck->m_Password, sizeof(char)*PktSSD::MaxPass);
return SendStream.WrapHeader(sizeof(PktSSD), CmdDBGetData, 0, usError);
}
return false;
}
// 캐릭터 로그인
bool CharLogin(CSendStream& SendStream, DataStorage::CSessionData& SessionData,
unsigned long dwRequestKey)
{
// DBAgent에 캐릭터 로그인 결과가 날아왔다.
// DB에서 정보를 읽어와 DataStorage::CCharacterData 에 정보를 저정한다.
const unsigned long MAX_BUFFER_SIZE = sizeof(PktDBUpdate) + DBUpdateData::MAX_DBUPDATE_SIZE;
char szBuffer[MAX_BUFFER_SIZE] = {0,};
unsigned long dwBufferSize = MAX_BUFFER_SIZE;
DataStorage::CCharacterData* lpCharacterData = SessionData.GetCharacterData();
DataStorage::CStoreData* lpStoreData = SessionData.GetStoreData();
if(0 == lpCharacterData || 0 == lpStoreData)
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / CCharacterData:%p / CStoreData:%p / "
"캐릭터 로그인 전송 실패 : 데이터가 없습니다.",
SessionData.GetUID(), SessionData.GetCID(), lpCharacterData, lpStoreData);
}
else
{
unsigned long dwUID = SessionData.GetUID();
unsigned long dwCID = lpCharacterData->GetCID();
PktDBUpdate* lpPktDBUpdate = reinterpret_cast<PktDBUpdate*>(szBuffer);
char* lpDataPos = szBuffer + sizeof(PktDBUpdate);
unsigned long dwDataSize = MAX_BUFFER_SIZE - sizeof(PktDBUpdate);
memset(lpPktDBUpdate, 0, sizeof(PktDBUpdate));
if(!lpCharacterData->SerializeOut(lpDataPos, lpPktDBUpdate->m_usUpdate,
dwDataSize, DBUpdateData::MAX_UPDATE_DB))
{
ERRLOG2(g_Log, "UID:%10u / CID:%10u / 캐릭터 로그인 전송 실패 : 캐릭터 데이터 SerializeOut에 실패했습니다.",
SessionData.GetUID(), SessionData.GetCID());
}
else
{
// 플레이어 타음을 업데이트 해준다.
// 로그인 한다.
if (GameRYL::CHINA == CServerSetup::GetInstance().GetNationType())
{
DBComponent::GameDB::UpdatePlayTime(CDBSingleObject::GetInstance(), dwUID, 0);
SessionData.GetPlayTimeFromDB(CDBSingleObject::GetInstance());
}
// 프리미엄 서비스 타임 설정
DBComponent::GameDB::UpdatePremiumService(CDBSingleObject::GetInstance(), dwUID, 0);
SessionData.GetPremiumServiceFromDB(CDBSingleObject::GetInstance());
unsigned char cAdminLevel = SessionData.GetAdminLevel();
DBUpdateData::UpdateType eUpdateType =
(0 != cAdminLevel) ? DBUpdateData::ADMIN_LOGIN : DBUpdateData::LOGIN;
// 용병 정보.
CGuildDB* lpGuild = static_cast<CGuildDB*>(
CGuildDBMgr::GetInstance().GetGuild(lpCharacterData->GetGID()));
unsigned char cTacticsFlag = 0;
if(lpGuild)
{
cTacticsFlag = lpGuild->GetTacticsMember(dwCID);
}
lpPktDBUpdate->m_dlItemSerial = 0;
lpPktDBUpdate->m_dwSessionID = SessionData.GetSessionID();
lpPktDBUpdate->m_dwUserID = dwUID;
lpPktDBUpdate->m_dwCharID = dwCID;
lpPktDBUpdate->m_dwRequestKey = dwRequestKey;
lpPktDBUpdate->m_Address = SessionData.GetRemoteAddress();
lpPktDBUpdate->m_cAdminLevel = cAdminLevel;
lpPktDBUpdate->m_cAdminFlag = lpCharacterData->GetAdminFlag();
lpPktDBUpdate->m_cTacticsFlag = cTacticsFlag;
strncpy(lpPktDBUpdate->m_szAccountName,
SessionData.GetAccountName(), CHAR_INFOST::MAX_ACCOUNT_LEN);
lpPktDBUpdate->m_szAccountName[CHAR_INFOST::MAX_ACCOUNT_LEN - 1] = 0;
// WORK_LIST 2.4 계정 국적을 게임서버의 캐릭터가 가지도록 구현
lpPktDBUpdate->m_cAccountNation = SessionData.GetAccountNation();
lpPktDBUpdate->m_cNameChangeCount = lpCharacterData->GetInfoEx().cNameChangeCount;
// 인스턴스 전쟁 참여 플래그인데 전쟁 시간이 아니면 OFF 로 바꿔준다.
if (lpCharacterData->GetInfoEx().GuildWarFlag == Creature::WAR_INSTANCE &&
!CGameTimeDBMgr::GetInstance().IsGuildWarTime())
{
lpCharacterData->SetGuildWarFlag(Creature::WAR_OFF);
}
if (lpCharacterData->GetInfoEx().RealmWarFlag == Creature::WAR_INSTANCE &&
!CGameTimeDBMgr::GetInstance().IsRealmWarReadyTime() &&
!CGameTimeDBMgr::GetInstance().IsRealmWarTime())
{
lpCharacterData->SetRealmWarFlag(Creature::WAR_OFF);
}
lpPktDBUpdate->m_cGuildWarFlag = lpCharacterData->GetInfoEx().GuildWarFlag;
lpPktDBUpdate->m_cRealmWarFlag = lpCharacterData->GetInfoEx().RealmWarFlag;
lpPktDBUpdate->m_cRealmPoint = lpCharacterData->GetInfoEx().RealmPoint;
lpPktDBUpdate->m_TypeCode = static_cast<unsigned short>(eUpdateType);
lpPktDBUpdate->m_PlayTime = SessionData.GetPlayTime();
lpPktDBUpdate->m_PremiumTime = SessionData.GetPremiumTime();
lpPktDBUpdate->m_PremiumType = SessionData.GetPremiumType();
if(!SendStream.WrapCompress(szBuffer,
static_cast<unsigned short>(sizeof(PktDBUpdate) + dwDataSize), CmdDBUpdateData, 0, 0))
{
// 캐릭터 로그인 전송 실패
return false;
}
// 일단 캐릭터 로그인이 전송 완료된 이후는,
unsigned long dwGID = lpCharacterData->GetGID();
unsigned short wClass = lpCharacterData->GetClass();
char cLevel = lpCharacterData->GetLevel();
// Friend 정보 설정 (시간이 생기면 수정하겠음) //
unsigned long dwMemberCID[CFriendList::MAX_FRIENDS_NUM] = {0,};
// 친구리스트에 CID 만 가지고 온다. //
CFriendList friendList = lpCharacterData->GetFriendList();
friendList.GetCIDList(dwMemberCID);
for(unsigned char cIndex = 0; cIndex < friendList.GetFriendNum(); cIndex++)
{
DataStorage::CSessionData* lpTargetSessionData = DataStorage::CSessionDataMgr::GetInstance().GetCharLoadedSession(dwMemberCID[cIndex]);
CFriendList::Rebind* lpRebind = friendList.GetFriend(dwMemberCID[cIndex]);
if(lpRebind)
{
if(lpTargetSessionData)
{
DataStorage::CCharacterData* lpTargetCharacterData = lpTargetSessionData->GetCharacterData();
if(lpTargetCharacterData)
{
if (DataStorage::CSessionData::SE_USER_ENABLED != lpTargetSessionData->GetSessionState() &&
DataStorage::CSessionData::SE_CHAR_ENABLED != lpTargetSessionData->GetSessionState())
{
lpRebind->UpdateServerID(0);
}
else
{
// Frind 초기화 //
lpRebind->InitializeFriendInfo(lpTargetCharacterData->GetServerID(), lpTargetCharacterData->GetGID(),
lpTargetCharacterData->GetClass(), lpTargetCharacterData->GetLevel());
}
}
else
{
lpRebind->UpdateServerID(0);
}
}
else
{
lpRebind->UpdateServerID(0);
}
}
}
// 친구 리스트 전송
dwBufferSize = MAX_BUFFER_SIZE;
if(friendList.SerializeOut(szBuffer, dwBufferSize))
{
SendPacket::Friend(SendStream, PktFriendDB::CMD::FRIEND_LIST, dwRequestKey, dwUID, dwCID,
dwGID, wClass, cLevel, SessionData.GetServerID(), szBuffer, dwBufferSize);
}
// Ban 정보 설정 (시간이 생기면 여기도 수정하겠음) //
CBanList banList = lpCharacterData->GetBanList();
// 거부리스트에 CID 만 가지고 온다. //
banList.GetCIDList(dwMemberCID);
for(unsigned char cIndex = 0; cIndex < banList.GetBanNum(); cIndex++)
{
DataStorage::CSessionData* lpTargetSessionData = DataStorage::CSessionDataMgr::GetInstance().GetCharLoadedSession(dwMemberCID[cIndex]);
CBanList::Rebind* lpRebind = banList.GetBan(dwMemberCID[cIndex]);
if(lpRebind)
{
if(lpTargetSessionData)
{
DataStorage::CCharacterData* lpTargetCharacterData = lpTargetSessionData->GetCharacterData();
if(lpTargetCharacterData)
{
if (DataStorage::CSessionData::SE_USER_ENABLED != lpTargetSessionData->GetSessionState() &&
DataStorage::CSessionData::SE_CHAR_ENABLED != lpTargetSessionData->GetSessionState())
{
lpRebind->UpdateServerID(0);
}
else
{
// Frind 초기화 //
lpRebind->InitializeBanInfo(lpTargetCharacterData->GetServerID(), lpTargetCharacterData->GetGID(),
lpTargetCharacterData->GetClass(), lpTargetCharacterData->GetLevel());
}
}
else
{
lpRebind->UpdateServerID(0);
}
}
else
{
lpRebind->UpdateServerID(0);
}
}
}
// 거부 리스트 전송
dwBufferSize = MAX_BUFFER_SIZE;
if(banList.SerializeOut(szBuffer, dwBufferSize))
{
SendPacket::Friend(SendStream, PktFriendDB::CMD::BAN_LIST, dwRequestKey, dwUID, dwCID,
dwGID, wClass, cLevel, SessionData.GetServerID(), szBuffer, dwBufferSize);
}
// 퀘스트 전송
const QUEST& quest = lpCharacterData->GetQuest();
const HISTORY& history = lpCharacterData->GetHistory();
SendPacket::Quest(SendStream, dwRequestKey, dwUID, dwCID,
quest.Data, quest.dwSize, history.Data, history.dwSize);
// 설정 전송
const CONFIG& config = lpCharacterData->GetConfig();
SendPacket::ConfigInfo(SendStream, dwRequestKey, dwUID, dwCID, config.Data, config.dwSize);
const STORE_INFO& storeInfo = lpStoreData->GetStoreInfo();
// 창고 패스워드 및 창고 금액 전송. 반드시 DepositDBUpdate보다 먼저 보내야 한다.
SendPacket::DepositData(SendStream, PktDeposit::CMD::PASSWORD, dwRequestKey, dwCID, storeInfo);
SendPacket::DepositData(SendStream, PktDeposit::CMD::GOLD, dwRequestKey, dwCID, storeInfo);
// 창고 전송
const STORE& store1 = lpStoreData->GetStore1();
const STORE& store2 = lpStoreData->GetStore2();
if (0 == store2.dwSize)
{
SendPacket::DepositDBUpdate(SendStream, dwRequestKey, dwUID, dwCID,
PktDepositUpdateDB::TabNum::TAB_12, true, storeInfo, store1);
}
else
{
SendPacket::DepositDBUpdate(SendStream, dwRequestKey, dwUID, dwCID,
PktDepositUpdateDB::TabNum::TAB_12, false, storeInfo, store1);
SendPacket::DepositDBUpdate(SendStream, dwRequestKey, dwUID, dwCID,
PktDepositUpdateDB::TabNum::TAB_34, true, storeInfo, store2);
}
// 파티 로그인 처리
CPartyDBInfo* lpParty = CPartyDBMgr::GetInstance().OpenParty(
CDBSingleObject::GetInstance(), lpCharacterData->GetPID());
if (0 != lpParty)
{
CPartyDBMgr::GetInstance().LoginPartyMember(
lpParty, dwUID, dwCID, dwGID, wClass, SessionData.GetServerID(), cLevel);
}
// 길드 로그인 처리
if (0 != lpGuild)
{
lpGuild->SendLoginOutMember(dwCID, SessionData.GetServerID());
}
// 듀얼시 연사 방지 패킷.
DataStorage::CSessionData::SaveEnemy* lpSaveEnemyInfo = SessionData.GetSaveEnemy();
unsigned long dwSaveEnemySize = sizeof(PktSaveEnemy) + sizeof(DataStorage::CSessionData::SaveEnemy)*4;
char* szSaveEnemyBuffer = SendStream.GetBuffer(dwSaveEnemySize);
PktSaveEnemy* lpPktSaveEnemy = reinterpret_cast<PktSaveEnemy*>(szSaveEnemyBuffer);
lpPktSaveEnemy->m_dwCID = SessionData.GetCID();
DataStorage::CSessionData::SaveEnemy* lpPktSaveEnemyInfo = NULL;
unsigned long dwTick = ::GetTickCount();
for(unsigned char cIndex = 0; cIndex < DataStorage::CSessionData::SaveEnemy::MAX_SAVING_ENEMY; cIndex++)
{
if(!cIndex)
{
lpPktSaveEnemy->m_dwAttackedCID = lpSaveEnemyInfo[cIndex].m_dwCID;
lpPktSaveEnemy->m_dwTick = dwTick - lpSaveEnemyInfo[cIndex].m_dwTick;
lpPktSaveEnemyInfo = reinterpret_cast<DataStorage::CSessionData::SaveEnemy*>(szSaveEnemyBuffer+sizeof(PktSaveEnemy));
}
else
{
lpPktSaveEnemyInfo[cIndex-1].m_dwCID = lpSaveEnemyInfo[cIndex].m_dwCID;
lpPktSaveEnemyInfo[cIndex-1].m_dwTick = 0;
if(lpSaveEnemyInfo[cIndex].m_dwCID)
{
lpPktSaveEnemyInfo[cIndex-1].m_dwTick = dwTick - lpSaveEnemyInfo[cIndex].m_dwTick;
}
}
}
if(!SendStream.WrapHeader((unsigned short)dwSaveEnemySize, CmdSaveEnemy, 0, 0))
{
return false;
}
// 조이스틱 키 정보.
KeyInfo* pKeyInfo = SessionData.GetKeyInfo();
if (pKeyInfo && pKeyInfo->m_cUsed)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktKeyInfo));
if(0 != lpBuffer)
{
PktKeyInfo* pPktKeyInfo = reinterpret_cast<PktKeyInfo*>(lpBuffer);;
pPktKeyInfo->m_dwCID = dwCID;
memcpy(pPktKeyInfo->m_dwKeyInfo, pKeyInfo->m_dwKeyInfo, sizeof(unsigned long)*PktKeyInfo::MAX_KEY_INFO);
SendStream.WrapCrypt(sizeof(PktKeyInfo), CmdKeyInfo, 0, 0);
}
}
// 로그 출력
SessionData.LogCharData("캐릭터 로그인");
}
}
return true;
}
// 캐릭터 로그인 실패.
bool CharLoginError(CSendStream& SendStream, unsigned long dwRequestKey,
DBUpdateData::UpdateType eUpdateType,
unsigned long dwUID, unsigned long dwCID, unsigned short usError)
{
if(0 != usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktDBUpdate));
if(0 != lpBuffer)
{
PktDBUpdate* lpPktDBUpdate = reinterpret_cast<PktDBUpdate*>(lpBuffer);
memset(lpPktDBUpdate, 0, sizeof(PktDBUpdate));
lpPktDBUpdate->m_dlItemSerial = 0;
lpPktDBUpdate->m_dwSessionID = 0;
lpPktDBUpdate->m_dwUserID = dwUID;
lpPktDBUpdate->m_dwCharID = dwCID;
lpPktDBUpdate->m_dwRequestKey = dwRequestKey;
lpPktDBUpdate->m_Address.S_un.S_addr = 0;
lpPktDBUpdate->m_cAdminLevel = 0;
// WORK_LIST 2.4 계정 국적을 게임서버의 캐릭터가 가지도록 구현
lpPktDBUpdate->m_cAccountNation = 0;
lpPktDBUpdate->m_cNameChangeCount = 0;
lpPktDBUpdate->m_cGuildWarFlag = 0;
lpPktDBUpdate->m_cRealmWarFlag = 0;
lpPktDBUpdate->m_cTacticsFlag = 0;
lpPktDBUpdate->m_TypeCode = static_cast<unsigned short>(eUpdateType);
memset(lpPktDBUpdate->m_usUpdate, 0,
sizeof(unsigned short) * DBUpdateData::MAX_UPDATE_DB);
return SendStream.WrapCrypt(sizeof(PktDBUpdate), CmdDBUpdateData, 0, usError);
}
}
return false;
}
bool Friend(CSendStream& SendStream, unsigned char cCmd, unsigned long dwRequestKey, unsigned long dwUID, unsigned long dwCID,
unsigned long dwGID, unsigned short wClass, char cLevel, unsigned long dwServerID, const char* lpData, unsigned long dwDataLen)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktFriendDB) + dwDataLen);
if(0 != lpBuffer)
{
PktFriendDB* lpFriendDB = reinterpret_cast<PktFriendDB*>(lpBuffer);
lpFriendDB->m_cCmd = cCmd;
lpFriendDB->m_dwRequestKey = dwRequestKey;
lpFriendDB->m_wCmd = 0;
lpFriendDB->m_dwOwnerUID = dwUID;
lpFriendDB->m_dwOwnerCID = dwCID;
lpFriendDB->m_dwReferenceCID = 0;
lpFriendDB->m_dwData = dwDataLen;
lpFriendDB->m_dwGID = dwGID;
lpFriendDB->m_wClass = wClass;
lpFriendDB->m_cLevel = cLevel;
lpFriendDB->m_dwServerID = dwServerID;
memcpy(lpFriendDB + 1, lpData, dwDataLen);
return SendStream.WrapHeader(
static_cast<unsigned short>(sizeof(PktFriendDB) + dwDataLen), CmdFriendDB, 0, 0);
}
return false;
}
bool Quest(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
const char* lpQuestBuffer, unsigned long dwQuestSize,
const char* lpHistoryBuffer, unsigned long dwHistorySize)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktQuestDB) + dwQuestSize + dwHistorySize);
if(0 != lpBuffer)
{
PktQuestDB* lpPktQuestDB = reinterpret_cast<PktQuestDB*>(lpBuffer);
lpPktQuestDB->m_dwRequestKey = dwRequestKey;
lpPktQuestDB->m_wCmd = 0;
lpPktQuestDB->m_dwUID = dwUID;
lpPktQuestDB->m_dwCID = dwCID;
lpPktQuestDB->m_wExecuteQuestSize = static_cast<unsigned short>(dwQuestSize);
lpPktQuestDB->m_wHistoryQuestSize = static_cast<unsigned short>(dwHistorySize);
memcpy(lpBuffer + sizeof(PktQuestDB), lpQuestBuffer, dwQuestSize);
memcpy(lpBuffer + sizeof(PktQuestDB) + dwQuestSize, lpHistoryBuffer, dwHistorySize);
return SendStream.WrapHeader(
static_cast<unsigned short>(sizeof(PktQuestDB) + dwQuestSize + dwHistorySize),
CmdQuestDB, 0, 0);
}
return false;
}
bool ConfigInfo(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
const char* lpConfigBuffer, unsigned long dwConfigSize)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktConfigInfo) + dwConfigSize);
if(0 != lpBuffer)
{
PktConfigInfo* lpConfigInfo = reinterpret_cast<PktConfigInfo*>(lpBuffer);
lpConfigInfo->m_dwRequestKey = dwRequestKey;
lpConfigInfo->m_wCmd = 0;
lpConfigInfo->m_dwUserID = dwUID;
lpConfigInfo->m_dwCharID = dwCID;
lpConfigInfo->m_wSize = static_cast<unsigned short>(dwConfigSize);
memcpy(lpBuffer + sizeof(PktConfigInfo), lpConfigBuffer, dwConfigSize);
return SendStream.WrapHeader(
static_cast<unsigned short>(sizeof(PktConfigInfo) + dwConfigSize), CmdConfigInfoDB, 0, 0);
}
return false;
}
bool DepositData(CSendStream& SendStream, unsigned char cCmd, unsigned long dwRequestKey,
unsigned long dwCID, const STORE_INFO& storeInfo)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktDeposit));
if(0 != lpBuffer)
{
PktDeposit* lpPktDeposit = reinterpret_cast<PktDeposit*>(lpBuffer);
lpPktDeposit->m_cCmd = cCmd;
lpPktDeposit->m_wCmd = 0;
lpPktDeposit->m_dwRequestKey = dwRequestKey;
if (PktDeposit::CMD::PASSWORD == cCmd)
{
memcpy(&lpPktDeposit->m_szData[0], &dwCID, sizeof(unsigned long));
memcpy(&lpPktDeposit->m_szData[4], storeInfo.Password, Deposit::PASSWORD_LENGTH);
}
else if (PktDeposit::CMD::GOLD == cCmd)
{
memcpy(&lpPktDeposit->m_szData[0], &dwCID, sizeof(unsigned long));
memcpy(&lpPktDeposit->m_szData[4], &storeInfo.Gold, sizeof(unsigned long));
}
return SendStream.WrapHeader(sizeof(PktDeposit), CmdDeposit, 0, 0);
}
return false;
}
bool DepositDBUpdate(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwCID,
unsigned char cTabNum, bool bComplete,
const STORE_INFO& storeInfo, const STORE& store)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktDepositUpdateDB) + store.dwSize);
if(0 != lpBuffer)
{
PktDepositUpdateDB* lpPktDepositUpdateDB =
reinterpret_cast<PktDepositUpdateDB*>(lpBuffer);
lpPktDepositUpdateDB->m_dwRequestKey = dwRequestKey;
lpPktDepositUpdateDB->m_wCmd = 0;
lpPktDepositUpdateDB->m_dwUID = dwUID;
lpPktDepositUpdateDB->m_dwCID = dwCID;
lpPktDepositUpdateDB->m_dwTabFlag = storeInfo.Flag;
lpPktDepositUpdateDB->m_usDataSize = static_cast<unsigned short>(store.dwSize);
lpPktDepositUpdateDB->m_cTabNum = cTabNum;
lpPktDepositUpdateDB->m_bUpdateComplete = bComplete;
memcpy(lpBuffer + sizeof(PktDepositUpdateDB), store.Data, store.dwSize);
return SendStream.WrapHeader(
static_cast<unsigned short>(sizeof(PktDepositUpdateDB) + store.dwSize), CmdDepositUpdate, 0, 0);
}
return false;
}
}
}

View File

@@ -0,0 +1,35 @@
#ifndef _DBAGENT_SERVER_SEND_LOGIN_OUT_H_
#define _DBAGENT_SERVER_SEND_LOGIN_OUT_H_
#include <Network/Packet/PacketStruct/CharLoginOutPacketStruct.h>
// forward decl.
class CSendStream;
namespace DBAgent
{
namespace DataStorage
{
// forward delc.
class CSessionData;
}
namespace SendPacket
{
// 세션 시작
bool StartSession(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned long dwUID, unsigned long dwSessionID,
unsigned char cFirstLogin, unsigned short usError);
// 캐릭터 로그인
bool CharLogin(CSendStream& SendStream,
DataStorage::CSessionData& SessionData, unsigned long dwRequestKey);
// 캐릭터 로그아웃
bool CharLoginError(CSendStream& SendStream, unsigned long dwRequestKey,
DBUpdateData::UpdateType eUpdateType,
unsigned long dwUID, unsigned long dwCID, unsigned short usError);
}
}
#endif

View File

@@ -0,0 +1,111 @@
#include "stdafx.h"
#include "SendMoveZone.h"
#include <Network/Stream/SendStream.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Utility/Setup/ServerSetup.h>
namespace DBAgent
{
namespace SendPacket
{
bool CharMoveZone(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSZMvDAck));
if(0 != lpBuffer)
{
PktSZMvDAck* lpPktSZMvDAck = reinterpret_cast<PktSZMvDAck*>(lpBuffer);
lpPktSZMvDAck->m_dwRequestKey = dwRequestKey;
lpPktSZMvDAck->m_wCmd = PktDD::SCmdCharMoveZone;
lpPktSZMvDAck->m_cZone = cZone;
CUserPercentageInZone getUserPercentage(
lpPktSZMvDAck->m_wChannelNum, cZone, PktSZMvDAck::MAX_CHANNEL_NUM);
CGameDispatch::GetDispatchTable().Process(getUserPercentage);
return SendStream.WrapHeader(sizeof(PktSZMvDAck), CmdAgentZone, 0, usError);
}
return false;
}
bool ServerZone(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned char cChannel, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSAAck));
if(0 != lpBuffer)
{
unsigned short usError = 0;
PktSAAck* lpPktSAAck = reinterpret_cast<PktSAAck*>(lpBuffer);
lpPktSAAck->m_dwRequestKey = dwRequestKey;
lpPktSAAck->m_wCmd = PktDD::SCmdServerZone;
lpPktSAAck->m_dwServerID = 0;
lpPktSAAck->m_GameAddress.S_un.S_addr = 0;
if(0 == usError)
{
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::GameServer;
serverID.sID.Group = CServerSetup::GetInstance().GetServerGroup();
serverID.sID.Channel = cChannel;
serverID.sID.ID = cZone;
GET_MULTI_DISPATCH(lpGameDispatch, serverID.dwID,
CGameDispatch, CGameDispatch::GetDispatchTable());
int nUserLimit = static_cast<int>(CServerSetup::GetInstance().GetUserLimit());
if(0 == lpGameDispatch)
{
usError = PktSAAck::SERVER_ERROR;
}
else if(nUserLimit < lpGameDispatch->GetCharNum())
{
usError = PktSAAck::FAIL_USER_LIMIT;
}
else
{
lpPktSAAck->m_dwServerID = lpGameDispatch->GetServerID();
lpPktSAAck->m_GameAddress = lpGameDispatch->GetRemoteAddr().get_addr_in().sin_addr;
}
}
return SendStream.WrapHeader(sizeof(PktSAAck), CmdAgentZone, 0, usError);
}
return false;
}
bool ServerZoneEnd(CSendStream& SendStream, unsigned long dwRequestKey)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktDD));
if(0 != lpBuffer)
{
PktDD* lpPktDD = reinterpret_cast<PktDD*>(lpBuffer);
lpPktDD->m_dwRequestKey = dwRequestKey;
lpPktDD->m_wCmd = PktDD::SCmdServerZoneEnd;
return SendStream.WrapHeader(sizeof(PktDD), CmdAgentZone, 0, 0);
}
return 0;
}
}
}

View File

@@ -0,0 +1,24 @@
#ifndef _DBAGENT_SERVER_SEND_MOVE_ZONE_H_
#define _DBAGENT_SERVER_SEND_MOVE_ZONE_H_
// forward decl.
class CSendStream;
namespace DBAgent
{
namespace SendPacket
{
bool CharMoveZone(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned short usError);
bool ServerZone(CSendStream& SendStream, unsigned long dwRequestKey,
unsigned char cZone, unsigned char cChannel, unsigned short usError = 0);
bool ServerZoneEnd(CSendStream& SendStream, unsigned long dwRequestKey);
}
}
#endif

View File

@@ -0,0 +1,111 @@
#include "stdafx.h"
#include "SendParty.h"
#include <Community/Party/PartyDBInfo.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/DataPacket.h>
#include <Network/Packet/PacketStruct/PartyPacket.h>
#include <Network/Dispatch/GameDispatch.h>
namespace DBAgent
{
namespace SendPacket
{
bool DeleteParty(CPartyDBInfo* lpParty)
{
if(0 != lpParty)
{
PktDPD pktDPD;
memset(&pktDPD, 0, sizeof(PktDPD));
pktDPD.m_wCmd = PktDD::SCmdDeleteParty;
pktDPD.m_dwPartyID = lpParty->GetPID();
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktDPD),
sizeof(PktDPD), CmdAgentParty, 0, 0))
{
CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktDPD), sizeof(PktDPD), CmdAgentParty));
return true;
}
}
return false;
}
bool PartyCmd(CSendStream& SendStream, unsigned short cSubCmd, unsigned long dwPID, unsigned long dwSenderID, unsigned long dwGID,
unsigned short wClass, unsigned long dwServerID, char cLevel, const char* szSenderName, unsigned short usError)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktPMD));
if(0 != lpBuffer)
{
PktPMD* lpPktPMD = reinterpret_cast<PktPMD*>(lpBuffer);
lpPktPMD->m_wCmd = cSubCmd;
lpPktPMD->m_dwPartyID = dwPID;
lpPktPMD->m_dwSenderID = dwSenderID;
lpPktPMD->m_dwGID = dwGID;
lpPktPMD->m_wClass = wClass;
lpPktPMD->m_dwServerID = dwServerID;
lpPktPMD->m_cLevel = cLevel;
if(0 != szSenderName)
{
strncpy(lpPktPMD->m_strSenderName, szSenderName, CHAR_INFOST::MAX_NAME_LEN);
lpPktPMD->m_strSenderName[CHAR_INFOST::MAX_NAME_LEN - 1] = 0;
}
else
{
memset(lpPktPMD->m_strSenderName, 0, sizeof(char) * CHAR_INFOST::MAX_NAME_LEN);
}
return SendStream.WrapHeader(sizeof(PktPMD), CmdAgentParty, 0, usError);
}
return false;
}
bool PartyCmd(unsigned short cSubCmd, unsigned long dwPID, unsigned long dwSenderID, unsigned long dwGID,
unsigned short wClass, unsigned long dwServerID, char cLevel, const char* szSenderName)
{
PktPMD pktPMD;
memset(&pktPMD, 0, sizeof(PktPMD));
pktPMD.m_wCmd = cSubCmd;
pktPMD.m_dwPartyID = dwPID;
pktPMD.m_dwSenderID = dwSenderID;
pktPMD.m_dwGID = dwGID;
pktPMD.m_wClass = wClass;
pktPMD.m_dwServerID = dwServerID;
pktPMD.m_cLevel = cLevel;
if (0 != szSenderName)
{
strncpy(pktPMD.m_strSenderName, szSenderName, CHAR_INFOST::MAX_NAME_LEN);
pktPMD.m_strSenderName[CHAR_INFOST::MAX_NAME_LEN - 1];
}
else
{
memset(pktPMD.m_strSenderName, 0, sizeof(char) * CHAR_INFOST::MAX_NAME_LEN);
}
if(PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktPMD),
sizeof(PktPMD), CmdAgentParty, 0, 0))
{
// 게임 서버로 브로드캐스팅 //
CGameDispatch::GetDispatchTable().Process(CSendPacketAllServer(
reinterpret_cast<char*>(&pktPMD), sizeof(PktPMD), CmdAgentParty));
return true;
}
return false;
}
}
}

View File

@@ -0,0 +1,23 @@
#ifndef _DBAGENT_SERVER_SEND_PARTY_H_
#define _DBAGENT_SERVER_SEND_PARTY_H_
// forward decl.
class CSendStream;
class CPartyDBInfo;
namespace DBAgent
{
namespace SendPacket
{
bool DeleteParty(CPartyDBInfo* lpParty);
bool PartyCmd(CSendStream& SendStream, unsigned short cSubCmd, unsigned long dwPID, unsigned long dwSenderID, unsigned long dwGID,
unsigned short wClass, unsigned long dwServerID, char cLevel, const char* szSenderName, unsigned short usError);
bool PartyCmd(unsigned short cSubCmd, unsigned long dwPID, unsigned long dwSenderID, unsigned long dwGID,
unsigned short wClass, unsigned long dwServerID, char cLevel, const char* szSenderName);
}
}
#endif

View File

@@ -0,0 +1,422 @@
#include "stdafx.h"
#include "SendServerInfo.h"
#include <Network/Stream/SendStream.h>
#include <Network/Winsock/SocketFactory.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/Dispatch/LoginDispatch.h>
#include <Network/Dispatch/AuthDispatch.h>
#include <Network/Dispatch/GameDispatch.h>
#include <Network/Dispatch/UIDDispatch.h>
#include <DataStorage/SessionData.h>
#include <Utility/Setup/ServerSetup.h>
#include <Log/ServerLog.h>
namespace DBAgent
{
namespace SendPacket
{
class CSendUpdateServerVersionAllGameServer
{
public:
bool operator () (unsigned long dwServer, CPacketDispatch& packetDispatch)
{
return DBAgent::SendPacket::UpdateServerVersion(
static_cast<DBAgent::CGameDispatch&>(packetDispatch).GetSendStream());
}
};
bool ServerLogin(CSendStream& SendStream, unsigned long dwServerID)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSL));
if(0 != lpBuffer)
{
const int MAX_ADDRESS = 64;
char szAddress[MAX_ADDRESS];
CTCPFactory tcpFactory;
tcpFactory.GetNetworkInfo(szAddress, MAX_ADDRESS);
PktSL* lpPktSL = reinterpret_cast<PktSL*>(lpBuffer);
lpPktSL->m_dwServerID = dwServerID;
lpPktSL->m_Address.S_un.S_addr = inet_addr(szAddress);
return SendStream.WrapHeader(sizeof(PktSL), CmdSysServerLogin, 0, 0);
}
return false;
}
bool ServerLoginAck(CSendStream& SendStream, unsigned long dwServerID,
unsigned __int64 dwItemSerial)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSLAck));
if(0 != lpBuffer)
{
PktSLAck* lpPktSLAck = reinterpret_cast<PktSLAck*>(lpBuffer);
CServerSetup& serverSetup = CServerSetup::GetInstance();
lpPktSLAck->m_dlItemUID = dwItemSerial;
lpPktSLAck->m_dwServerID = dwServerID;
lpPktSLAck->m_dwClientVer = serverSetup.GetClientVer();
lpPktSLAck->m_dwCheckSum = serverSetup.GetCheckSum();
strncpy(lpPktSLAck->m_PatchAddress,
serverSetup.GetPatchAddress(), PktSLAck::PATCH_ADDRESS_LENGTH - 1);
lpPktSLAck->m_PatchAddress[PktSLAck::PATCH_ADDRESS_LENGTH - 1] = 0;
return SendStream.WrapHeader(sizeof(PktSLAck), CmdSysServerLogin, 0, 0);
}
return false;
}
bool UpdateChannel(CSendStream& SendStream, unsigned long dwServerID)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSCInfo));
if(0 != lpBuffer)
{
PktSCInfo* lpPktSCInfo = reinterpret_cast<PktSCInfo*>(lpBuffer);
lpPktSCInfo->m_dwServerID = dwServerID;
CGetTotalCount getCount(
lpPktSCInfo->m_usChannelClientNum[0],
lpPktSCInfo->m_usChannelClientNum[1],
lpPktSCInfo->m_cChannelNum);
CGameDispatch::GetDispatchTable().Process(getCount);
if(0 < lpPktSCInfo->m_cChannelNum)
{
if(lpPktSCInfo->m_cChannelNum <= lpPktSCInfo->m_usChannelClientNum[0])
{
lpPktSCInfo->m_usChannelClientNum[0] -= lpPktSCInfo->m_cChannelNum;
++lpPktSCInfo->m_usChannelClientNum[0];
}
if(lpPktSCInfo->m_cChannelNum <= lpPktSCInfo->m_usChannelClientNum[1])
{
lpPktSCInfo->m_usChannelClientNum[1] -= lpPktSCInfo->m_cChannelNum;
++lpPktSCInfo->m_usChannelClientNum[1];
}
lpPktSCInfo->m_cChannelNum = 2;
}
return SendStream.WrapCrypt(sizeof(PktSCInfo), CmdSysChannelUpdate, 0, 0);
}
return false;
}
bool UpdateServerVersion(CSendStream& SendStream)
{
char* lpBuffer = SendStream.GetBuffer(sizeof(PktSVU));
if(0 != lpBuffer)
{
PktSVU* lpPktSVU = reinterpret_cast<PktSVU*>(lpBuffer);
CServerSetup& serverSetup = CServerSetup::GetInstance();
lpPktSVU->m_dwClientVer = serverSetup.GetClientVer();
lpPktSVU->m_dwCheckSum = serverSetup.GetCheckSum();
strncpy(lpPktSVU->m_PatchAddress, serverSetup.GetPatchAddress(),
PktSVU::PATCH_ADDRESS_LENGTH - 1);
lpPktSVU->m_PatchAddress[PktSVU::PATCH_ADDRESS_LENGTH - 1] = 0;
GET_SINGLE_DISPATCH(lpAuthDispatch,
CAuthDispatch, CAuthDispatch::GetDispatchTable());
if(0 != lpAuthDispatch)
{
lpPktSVU->m_ServerAddr = lpAuthDispatch->GetRemoteAddr().get_addr_in().sin_addr;
}
else
{
lpPktSVU->m_ServerAddr.S_un.S_addr = 0;
}
return SendStream.WrapCrypt(sizeof(PktSVU), CmdSysServerVerUpdate, 0, 0);
}
return false;
}
void UpdateChannelAllServer()
{
// 로그인 서버로 서버 버전 업데이트 보냄
GET_SINGLE_DISPATCH(lpLoginDispatch, DBAgent::CLoginDispatch,
DBAgent::CLoginDispatch::GetDispatchTable());
if(0 != lpLoginDispatch)
{
DBAgent::SendPacket::UpdateServerVersion(lpLoginDispatch->GetSendStream());
}
// 인증 서버로 서버 버전 업데이트 보냄
GET_SINGLE_DISPATCH(lpAuthDispatch, DBAgent::CAuthDispatch,
DBAgent::CAuthDispatch::GetDispatchTable());
if(0 != lpAuthDispatch)
{
DBAgent::SendPacket::UpdateServerVersion(lpAuthDispatch->GetSendStream());
}
// 게임 서버로 서버 버전 업데이트 보냄
DBAgent::CGameDispatch::GetDispatchTable().Process(
CSendUpdateServerVersionAllGameServer());
}
bool UpdateUIDTable(PktUUT::UpdateType eUpdateType, const char* szAccountName, const char* szPassword,
unsigned long dwUID, unsigned long dwCID, unsigned long dwSessionID,
unsigned long dwServerID, IN_ADDR peerAddr, unsigned short usError)
{
const char* szErrorReason = 0;
GET_SINGLE_DISPATCH(lpUIDDispatch, CUIDDispatch, CUIDDispatch::GetDispatchTable());
if(0 != lpUIDDispatch)
{
// edith 2008.01.15 UID 서버로 캐릭터 로그인 메시지를 전달한다.
// 이유는 캐릭터 로그인을 전달해 빌링서버에서 인증을 하기위함이다.
CSendStream& uidSendStream = lpUIDDispatch->GetSendStream();
char* lpBuffer = uidSendStream.GetBuffer(sizeof(PktUUT));
if(0 != lpBuffer)
{
PktUUT* lpPktUUT = reinterpret_cast<PktUUT*>(lpBuffer);
lpPktUUT->m_cCmd = static_cast<unsigned char>(eUpdateType);
ZeroMemory(lpPktUUT->m_strAccount, PktUUT::MaxAccountLen);
ZeroMemory(lpPktUUT->m_strPassword, PktUUT::MaxPasswordLen);
if(szAccountName && strlen(szAccountName) > 0)
{
strcpy(lpPktUUT->m_strAccount, szAccountName);
}
// edith 2008.01.15 패스워드 추가작업
if(szPassword && strlen(szPassword) > 0)
{
strcpy(lpPktUUT->m_strPassword, szPassword);
// strncpy(lpPktUUT->m_strPassword, szPassword, PktUUT::MaxPasswordLen - 1);
// lpPktUUT->m_strPassword[PktUUT::MaxPasswordLen - 1] = 0;
}
lpPktUUT->m_IPAddress = peerAddr;
lpPktUUT->m_dwSessionID = dwSessionID;
lpPktUUT->m_dwServerID = dwServerID;
lpPktUUT->m_dwUserID = dwUID;
lpPktUUT->m_dwCharID = dwCID;
if(uidSendStream.WrapHeader(sizeof(PktUUT), CmdUpdateUIDTable, 0, usError))
{
INFLOG3(g_Log, "UID:%10u / CID:%10u / ST:%s / UpdateUIDTable 전송 성공",
dwUID, dwCID, g_szPktUUTString[eUpdateType]);
return true;
}
else
{
szErrorReason = "WrapHeader 실패";
}
}
else
{
szErrorReason = "버퍼 할당 실패";
}
}
else
{
szErrorReason = "UID서버와 연결 끊어짐";
}
if(0 != szErrorReason)
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / ST:%s / UpdateUIDTable 전송 실패 : %s",
dwUID, dwCID, g_szPktUUTString[eUpdateType], szErrorReason);
}
return false;
}
bool UserKill(const DataStorage::CSessionData& SessionData)
{
SERVER_ID serverID;
serverID.dwID = SessionData.GetServerID();
CSendStream* lpSendStream = 0;
if(serverID.GetType() == CServerSetup::AuthServer)
{
GET_SINGLE_DISPATCH(lpAuthDispatch, CAuthDispatch,
CAuthDispatch::GetDispatchTable());
if(0 != lpAuthDispatch)
{
lpSendStream = &lpAuthDispatch->GetSendStream();
}
}
else if(serverID.GetType() == CServerSetup::GameServer)
{
GET_MULTI_DISPATCH(lpGameDispatch, serverID.dwID,
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 != lpGameDispatch)
{
lpSendStream = &lpGameDispatch->GetSendStream();
}
}
const char* szErrorReason = 0;
if(0 == lpSendStream)
{
szErrorReason = "해당 서버가 없습니다";
}
else
{
char* lpBuffer = lpSendStream->GetBuffer(sizeof(PktUK));
if(0 == lpBuffer)
{
szErrorReason = "버퍼 할당 실패";
}
else
{
PktUK* lpPktUK = reinterpret_cast<PktUK*>(lpBuffer);
lpPktUK->m_dwUserID = SessionData.GetUID();
lpPktUK->m_dwCharID = SessionData.GetCID();
lpPktUK->m_dwServerID = SessionData.GetServerID();
if(!lpSendStream->WrapHeader(sizeof(PktUK), CmdUserKill, 0, 0))
{
szErrorReason = "전송 실패";
}
}
}
if(0 != szErrorReason)
{
ERRLOG4(g_Log, "UID:%10u / CID:%10u / ServerID:0x%08X / 유저 죽이기 전송 실패 : %s",
SessionData.GetUID(), SessionData.GetCID(), SessionData.GetServerID(), szErrorReason);
return false;
}
INFLOG3(g_Log, "UID:%10u / CID:%10u / ServerID:0x%08X / 유저 죽이기 전송 성공",
SessionData.GetUID(), SessionData.GetCID(), SessionData.GetServerID());
return true;
}
bool BillingNotify(const DataStorage::CSessionData& SessionData,
unsigned char cRemainMinute, char cBillingType)
{
GET_MULTI_DISPATCH(lpGameDispatch, SessionData.GetServerID(),
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 != lpGameDispatch)
{
CSendStream& SendStream = lpGameDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktBTN));
if(0 != lpBuffer)
{
PktBTN* lpPktBTN = reinterpret_cast<PktBTN*>(lpBuffer);
lpPktBTN->m_dwUserID = SessionData.GetUID();
lpPktBTN->m_dwCharID = SessionData.GetCID();
lpPktBTN->m_dwServerID = SessionData.GetServerID();
lpPktBTN->m_cRemainMinute = cRemainMinute;
lpPktBTN->m_cBillingType = cBillingType;
return SendStream.WrapHeader(sizeof(PktBTN), CmdBillingTimeoutNotify, 0, 0);
}
}
return false;
}
bool BillingCheckNotify(const DataStorage::CSessionData& SessionData,
unsigned char cRemainMinute, char cBillingType)
{
SERVER_ID serverID;
serverID.dwID = SessionData.GetServerID();
if (CServerSetup::AuthServer == serverID.GetType())
{
GET_SINGLE_DISPATCH(lpAuthDispatch,
CAuthDispatch, CAuthDispatch::GetDispatchTable());
CSendStream& SendStream = lpAuthDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktBTN));
if(0 != lpBuffer)
{
PktBTN* lpPktBTN = reinterpret_cast<PktBTN*>(lpBuffer);
lpPktBTN->m_dwUserID = SessionData.GetUID();
lpPktBTN->m_dwCharID = SessionData.GetCID();
lpPktBTN->m_dwServerID = SessionData.GetServerID();
lpPktBTN->m_cRemainMinute = cRemainMinute;
lpPktBTN->m_cBillingType = cBillingType;
return SendStream.WrapHeader(sizeof(PktBTN), CmdBillingTimeCheckNotify, 0, 0);
}
}
else if(CServerSetup::GameServer == serverID.GetType())
{
GET_MULTI_DISPATCH(lpGameDispatch, SessionData.GetServerID(),
CGameDispatch, CGameDispatch::GetDispatchTable());
if(0 != lpGameDispatch)
{
CSendStream& SendStream = lpGameDispatch->GetSendStream();
char* lpBuffer = SendStream.GetBuffer(sizeof(PktBTN));
if(0 != lpBuffer)
{
PktBTN* lpPktBTN = reinterpret_cast<PktBTN*>(lpBuffer);
lpPktBTN->m_dwUserID = SessionData.GetUID();
lpPktBTN->m_dwCharID = SessionData.GetCID();
lpPktBTN->m_dwServerID = SessionData.GetServerID();
lpPktBTN->m_cRemainMinute = cRemainMinute;
lpPktBTN->m_cBillingType = cBillingType;
return SendStream.WrapHeader(sizeof(PktBTN), CmdBillingTimeCheckNotify, 0, 0);
}
}
}
return false;
}
}
}

View File

@@ -0,0 +1,46 @@
#ifndef _DBAGENT_SERVER_SEND_SERVER_INFO_H_
#define _DBAGENT_SERVER_SEND_SERVER_INFO_H_
#include <Network/Packet/PacketStruct/ServerPacket.h>
// forward decl.
class CSendStream;
class CPacketDispatch;
namespace DBAgent
{
namespace DataStorage
{
// forward delc.
class CSessionData;
}
namespace SendPacket
{
bool ServerLogin(CSendStream& SendStream, unsigned long dwServerID);
bool ServerLoginAck(CSendStream& SendStream, unsigned long dwServerID,
unsigned __int64 dwItemSerial);
bool UpdateChannel(CSendStream& SendStream, unsigned long dwServerID);
bool UpdateServerVersion(CSendStream& SendStream);
void UpdateChannelAllServer();
bool UpdateUIDTable(PktUUT::UpdateType eUpdateType, const char* szAccountName, const char* szPassword,
unsigned long dwUID, unsigned long dwCID, unsigned long dwSessionID,
unsigned long dwServerID, IN_ADDR peerAddr, unsigned short usError = 0);
bool UserKill(const DataStorage::CSessionData& SessionData);
bool BillingNotify(const DataStorage::CSessionData& SessionData,
unsigned char cRemainMinute, char cBillingType);
// ´ë¸¸ÂÊ ºô¸µ üũ Notify
bool BillingCheckNotify(const DataStorage::CSessionData& SessionData,
unsigned char cRemainMinute, char cBillingType);
}
}
#endif