Files
Client/Server/RylServerProject/RylGameLibrary/Network/Broadcast/BroadcastCharacterData.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

390 lines
12 KiB
C++

#define NOMINMAX
#include "stdafx.h"
#include <Item/Item.h>
#include "BroadcastCharacterData.h"
#include <utility>
#include "GMMemory.h"
namespace Broadcast2nd
{
const unsigned char CNetworkEquipGrade::TransferNetworkEquipGrade(Item::CItem* lpItem)
{
Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem);
if (NULL != lpEquip)
{
Item::Grade::GradeInfo gradeInfo = lpEquip->GetItemGrade();
// A 그레이드부터 이펙트를 표기한다.
if (Item::EquipType::B_GRADE > gradeInfo.m_eItemGrade)
{
return (Item::EquipType::B_GRADE - gradeInfo.m_eItemGrade);
}
}
return 0;
}
CAggresiveCreatureData::CAggresiveCreatureData()
: m_dwCID(0), m_usHP(0), m_dwDataFlag(0), m_dwLastUpdatedPulse(0)
{
}
CAggresiveCreatureData::~CAggresiveCreatureData()
{
}
void CAggresiveCreatureData::SetEnchantInfo(const EnchantInfo& enchantInfo)
{
std::copy(enchantInfo.m_dwStatusFlag,
enchantInfo.m_dwStatusFlag + EnchantInfo::MAX_ARRAY, m_EnchantInfo.m_dwStatusFlag);
}
void CAggresiveCreatureData::ClearData()
{
m_dwCID = 0;
m_usHP = 0;
m_dwDataFlag = 0;
m_dwLastUpdatedPulse = 0;
m_NetworkPos.Initialize(0, 0, 0, 0, 0);
m_EnchantInfo.ClearFlag();
}
CCharacterData::CCharacterData()
{
memset(m_szName, 0, sizeof(char) * MAX_NAME);
memset(m_szStallName, 0, sizeof(char) * StallNode::MAX_STALL_NAME);
memset(m_dwDoubleEquipsID, 0, sizeof(unsigned long) * HALF_EQUIP_POS);
memset(&m_CommunityInfo, 0, sizeof(CommunityInfo));
memset(&m_StatusInfo, 0, sizeof(bcStatusInfo));
memset(&m_NetworkEquipGrade, 0, sizeof(CNetworkEquipGrade));
memset(&m_WarFlagInfo, 0, sizeof(WarFlagInfo));
memset(&m_cRealmPoint, 0, sizeof(unsigned char));
}
CCharacterData::~CCharacterData()
{
}
void CCharacterData::ClearData()
{
CAggresiveCreatureData::ClearData();
memset(m_szName, 0, sizeof(char) * MAX_NAME);
memset(m_szStallName, 0, sizeof(char) * StallNode::MAX_STALL_NAME);
memset(m_dwDoubleEquipsID, 0, sizeof(unsigned long) * HALF_EQUIP_POS);
memset(&m_CommunityInfo, 0, sizeof(CommunityInfo));
memset(&m_StatusInfo, 0, sizeof(bcStatusInfo));
memset(&m_NetworkEquipGrade, 0, sizeof(CNetworkEquipGrade));
memset(&m_WarFlagInfo, 0, sizeof(WarFlagInfo));
memset(&m_cRealmPoint, 0, sizeof(unsigned char));
}
void CCharacterData::GetEquipmentsID(unsigned short* lpEquipmentsID_Out, unsigned char nIDNum) const
{
unsigned short* dupEquipsID = (unsigned short*)m_dwDoubleEquipsID;
std::copy(dupEquipsID, dupEquipsID +
std::min(nIDNum, unsigned char(Item::EquipmentPos::MAX_EQUPMENT_POS)), lpEquipmentsID_Out);
}
void CCharacterData::SetEquipmentsID(unsigned short* lpEquipmentsID_In, const unsigned char nIDNum)
{
std::copy(lpEquipmentsID_In, lpEquipmentsID_In +
std::min(nIDNum, unsigned char(Item::EquipmentPos::MAX_EQUPMENT_POS)), reinterpret_cast<unsigned short*>(m_dwDoubleEquipsID));
}
void Broadcast2nd::CCharacterData::SetEquipmentsID(unsigned long dwEquipmentsID_In, const unsigned char nIDIndex)
{
if (nIDIndex < HALF_EQUIP_POS)
{
m_dwDoubleEquipsID[nIDIndex] = dwEquipmentsID_In;
}
}
void CCharacterData::SetName(const char* szName, const size_t nNameLen)
{
memcpy(m_szName, szName, std::min(size_t(MAX_NAME), nNameLen));
}
void CCharacterData::SetStallName(const char* szStallName, const size_t nStallNameLen)
{
memcpy(m_szStallName, szStallName, std::min(size_t(StallNode::MAX_STALL_NAME), nStallNameLen));
}
bool CCharacterData::UpdateData(unsigned long dwCID, unsigned long dwCurrentPulse,
const char* szData, int& nBufferSize_InOut)
{
// 데이터 순서는 다음과 같다.
// UpdateFlag(4byte)
// 장비들(16개 * 2byte = 32byte)
// 이름(16byte)
// 노점상 이름(32byte)
// 주소 정보 (public addr/private addr 12byte)
// 커뮤니티 정보 ( 길드ID / 파티ID / 용병 / 명성 / 마일리지 )
// 몸 정보 ( 4byte )
// 레벨 및
// Total 138 Bytes
unsigned long dwUpdateFlag = 0;
const char* szDataPos = szData;
const int nBufferSize = nBufferSize_InOut;
if (nBufferSize < sizeof(unsigned long))
{
return false;
}
COPY_AND_ADVANCE_SRC(&dwUpdateFlag, szDataPos, sizeof(unsigned long));
// 읽어온 UpdateFlag로, 필요한 데이터의 양을 추산한다. 데이터 양이 부족하면 에러를 뱉는다.
int nEstimateBufferSize = EstimateBufferSize(dwUpdateFlag);
if (nBufferSize < nEstimateBufferSize )
{
// 버퍼 크기가 추산한 길이보다 작은 경우는 실패
return false;
}
// 데이터 복사. 순서 바뀌면 죽는다!!.
m_dwCID = dwCID;
if (0 != dwCurrentPulse)
{
// Pulse가 0으로 오면 CellLogin이다. Pulse를 업데이트하지 않는다.
m_dwLastUpdatedPulse = dwCurrentPulse;
}
int nCount = 0;
for (; nCount < HALF_EQUIP_POS; ++nCount)
{
if (dwUpdateFlag & (1 << nCount))
{
COPY_AND_ADVANCE_SRC(m_dwDoubleEquipsID + nCount, szDataPos, sizeof(unsigned long));
}
}
if (dwUpdateFlag & CHAR_DELTA_CHAR_NAME) { COPY_AND_ADVANCE_SRC(m_szName, szDataPos, sizeof(unsigned char) * MAX_NAME); }
if (dwUpdateFlag & CHAR_DELTA_STALL_NAME) { COPY_AND_ADVANCE_SRC(m_szStallName, szDataPos, sizeof(unsigned char) * StallNode::MAX_STALL_NAME); }
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwGuild_ID, szDataPos, sizeof(unsigned long)); }
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_cTacticsFlag, szDataPos, sizeof(unsigned char)); }
if (dwUpdateFlag & CHAR_DELTA_PARTY_ID) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwParty_ID, szDataPos, sizeof(unsigned long)); }
if (dwUpdateFlag & CHAR_DELTA_FAME) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwFame, szDataPos, sizeof(unsigned long)); }
if (dwUpdateFlag & CHAR_DELTA_FAME) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwMileage, szDataPos, sizeof(unsigned long)); }
if (dwUpdateFlag & CHAR_DELTA_BODYINFO) { COPY_AND_ADVANCE_SRC(&m_StatusInfo.m_dwBodyInfo, szDataPos, sizeof(unsigned long)); }
if (dwUpdateFlag & CHAR_DELTA_CLASS) { COPY_AND_ADVANCE_SRC(&m_StatusInfo.m_cClass, szDataPos, sizeof(unsigned char)); }
if (dwUpdateFlag & CHAR_DELTA_LEVEL) { COPY_AND_ADVANCE_SRC(&m_StatusInfo.m_cLevel, szDataPos, sizeof(unsigned char)); }
for (nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
{
if (dwUpdateFlag & (CHAR_DELTA_ENCHANT_INFO << nCount))
{
COPY_AND_ADVANCE_SRC(m_EnchantInfo.m_dwStatusFlag + nCount, szDataPos, sizeof(unsigned long));
}
}
if (dwUpdateFlag & CHAR_DELTA_NETWORK_POS) { COPY_AND_ADVANCE_SRC(&m_NetworkPos, szDataPos, sizeof(CNetworkPos));}
if (dwUpdateFlag & CHAR_DELTA_HP) { COPY_AND_ADVANCE_SRC(&m_usHP, szDataPos, sizeof(unsigned short)); }
if (dwUpdateFlag & CHAR_DELTA_EQUIP_GRADE) { COPY_AND_ADVANCE_SRC(&m_NetworkEquipGrade, szDataPos, sizeof(CNetworkEquipGrade)); }
if (dwUpdateFlag & CHAR_DELTA_WAR_FLAG) { COPY_AND_ADVANCE_SRC(&m_WarFlagInfo, szDataPos, sizeof(WarFlagInfo)); }
if (dwUpdateFlag & CHAR_DELTA_REALM_POINT) { COPY_AND_ADVANCE_SRC(&m_cRealmPoint, szDataPos, sizeof(unsigned char)); }
nBufferSize_InOut = static_cast<int>(szDataPos - szData);
if (0 != dwUpdateFlag)
{
// 변경된 데이터가 있는지 살피고, 변경되었다면 데이터 변경 비트를 세팅한다.
SetDataFlag(CHARDATA_CHANGED);
}
return true;
}
int CCharacterData::EstimateBufferSize(unsigned long dwUpdateFlag)
{
// CID와 UpdateFlag의 길이만큼 더한다.
int nEstimateBufferSize = 0;
int nCount = 0;
for (; nCount < Broadcast2nd::CCharacterData::HALF_EQUIP_POS; ++nCount)
{
if (dwUpdateFlag & (1 << nCount))
{
nEstimateBufferSize += sizeof(unsigned long);
}
}
if (dwUpdateFlag & CHAR_DELTA_CHAR_NAME) { nEstimateBufferSize += sizeof(unsigned char) * MAX_NAME; }
if (dwUpdateFlag & CHAR_DELTA_STALL_NAME) { nEstimateBufferSize += sizeof(unsigned char) * StallNode::MAX_STALL_NAME; }
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { nEstimateBufferSize += sizeof(unsigned long); }
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { nEstimateBufferSize += sizeof(unsigned char); }
if (dwUpdateFlag & CHAR_DELTA_PARTY_ID) { nEstimateBufferSize += sizeof(unsigned long); }
if (dwUpdateFlag & CHAR_DELTA_FAME) { nEstimateBufferSize += sizeof(unsigned long) * 2; }
if (dwUpdateFlag & CHAR_DELTA_BODYINFO) { nEstimateBufferSize += sizeof(unsigned long); }
if (dwUpdateFlag & CHAR_DELTA_CLASS) { nEstimateBufferSize += sizeof(unsigned char); }
if (dwUpdateFlag & CHAR_DELTA_LEVEL) { nEstimateBufferSize += sizeof(unsigned char); }
for (nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
{
if (dwUpdateFlag & (CHAR_DELTA_ENCHANT_INFO << nCount))
{
nEstimateBufferSize += sizeof(unsigned long);
}
}
if (dwUpdateFlag & CHAR_DELTA_NETWORK_POS) { nEstimateBufferSize += sizeof(CNetworkPos); }
if (dwUpdateFlag & CHAR_DELTA_HP) { nEstimateBufferSize += sizeof(unsigned short); }
if (dwUpdateFlag & CHAR_DELTA_EQUIP_GRADE) { nEstimateBufferSize += sizeof(CNetworkEquipGrade); }
if (dwUpdateFlag & CHAR_DELTA_WAR_FLAG) { nEstimateBufferSize += sizeof(WarFlagInfo); }
if (dwUpdateFlag & CHAR_DELTA_REALM_POINT) { nEstimateBufferSize += sizeof(unsigned char); }
return nEstimateBufferSize;
}
void CMonsterData::ClearData()
{
CAggresiveCreatureData::ClearData();
m_dwMasterCID = 0;
}
CMonsterData::CMonsterData()
: m_dwMasterCID(0)
{
}
CMonsterData::~CMonsterData()
{
}
bool CMonsterData::UpdateData(unsigned long dwCID, unsigned long dwCurrentPulse,
const char* szData, int& nBufferSize_InOut)
{
const char* szDataPos = szData;
const int nBufferSize = nBufferSize_InOut;
if (nBufferSize < sizeof(unsigned char))
{
return false;
}
unsigned char cUpdateFlag =
*reinterpret_cast<const unsigned char*>(szDataPos);
++szDataPos;
// 읽어온 UpdateFlag로, 필요한 데이터의 양을 추산한다. 데이터 양이 부족하면 에러를 뱉는다.
int nEstimateBufferSize = EstimateBufferSize(cUpdateFlag);
if (nBufferSize < nEstimateBufferSize)
{
// 버퍼 크기가 추산한 길이보다 작은 경우는 실패
return false;
}
// 데이터 복사. 순서 바뀌면 죽는다!!.
m_dwCID = dwCID;
if (0 != dwCurrentPulse)
{
// Pulse가 0으로 오면 CellLogin이다. Pulse를 업데이트하지 않는다.
m_dwLastUpdatedPulse = dwCurrentPulse;
}
for (int nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
{
if (cUpdateFlag & (MON_DELTA_ENCHANT_INFO << nCount))
{
COPY_AND_ADVANCE_SRC(
m_EnchantInfo.m_dwStatusFlag + nCount,
szDataPos, sizeof(unsigned long));
}
}
const CNetworkPos oldNetPos = m_NetworkPos;
if (cUpdateFlag & MON_DELTA_NETWORK_POS) { COPY_AND_ADVANCE_SRC(&m_NetworkPos, szDataPos, sizeof(CNetworkPos)); }
if (cUpdateFlag & MON_DELTA_HP) { COPY_AND_ADVANCE_SRC(&m_usHP, szDataPos, sizeof(unsigned short)); }
if (cUpdateFlag & MON_DELTA_MASTERCID) { COPY_AND_ADVANCE_SRC(&m_dwMasterCID, szDataPos, sizeof(unsigned long)); }
/*
// TODO : REMOVE HERE
if (49 < oldNetPos.GetSquaredRange(CNetworkPos(0, 0, 0)) &&
49 < oldNetPos.GetSquaredRange(m_NetworkPos))
{
const int MAX_BUFFER = 256;
char szBuffer[MAX_BUFFER];
if (0 < _snprintf(szBuffer, MAX_BUFFER - 1,
"PktBroadcast2nd : CID:0x%08x : 순간이동하나?.. %f거리를 눈앞에서 이동했다!"
"/CurrentPulse:%d (%f,%f,%f)->(%f,%f,%f)\n",
m_dwCID, oldNetPos.GetSquaredRange(m_NetworkPos), dwCurrentPulse,
oldNetPos.GetXPos(), oldNetPos.GetYPos(), oldNetPos.GetZPos(),
m_NetworkPos.GetXPos(), m_NetworkPos.GetYPos(), m_NetworkPos.GetZPos()))
{
szBuffer[MAX_BUFFER - 1] = 0;
OutputDebugString(szBuffer);
}
}
*/
nBufferSize_InOut = static_cast<int>(szDataPos - szData);
if (0 != cUpdateFlag)
{
// 변경된 데이터가 있는지 살피고, 변경되었다면 데이터 변경 비트를 세팅한다.
SetDataFlag(CHARDATA_CHANGED);
}
return true;
}
int CMonsterData::EstimateBufferSize(unsigned char cUpdateFlag)
{
// CID와 UpdateFlag의 길이만큼 더한다.
int nEstimateBufferSize = 0;
int nCount = 0;
for (nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
{
if (cUpdateFlag & (MON_DELTA_ENCHANT_INFO << nCount))
{
nEstimateBufferSize += sizeof(unsigned long);
}
}
if (cUpdateFlag & MON_DELTA_NETWORK_POS) { nEstimateBufferSize += sizeof(CNetworkPos); }
if (cUpdateFlag & MON_DELTA_HP) { nEstimateBufferSize += sizeof(unsigned short); }
if (cUpdateFlag & MON_DELTA_MASTERCID) { nEstimateBufferSize += sizeof(unsigned long); }
return nEstimateBufferSize;
}
}