QoL: Server-Side mark broadcast P2P

This commit is contained in:
rtw1x1
2026-01-21 18:31:58 +00:00
parent 7f2c842f6d
commit 7c615a7a84
9 changed files with 110 additions and 39 deletions

View File

@@ -242,6 +242,31 @@ DWORD CGuildMarkManager::SaveMark(DWORD guildID, BYTE * pbMarkImage)
return idMark;
}
// SERVER - Allocate a mark slot with default (empty) image for a new guild
DWORD CGuildMarkManager::AllocMark(DWORD guildID)
{
// Check if guild already has a mark
if (GetMarkID(guildID) != INVALID_MARK_ID)
{
sys_log(0, "AllocMark: guild %u already has a mark", guildID);
return GetMarkID(guildID);
}
DWORD idMark = __AllocMarkID(guildID);
if (idMark == INVALID_MARK_ID)
{
sys_err("CGuildMarkManager::AllocMark: cannot alloc mark id for guild %u", guildID);
return INVALID_MARK_ID;
}
sys_log(0, "AllocMark: allocated mark id %u for guild %u", idMark, guildID);
// Save the index so the mark slot is persisted
SaveMarkIndex();
return idMark;
}
// SERVER
void CGuildMarkManager::DeleteMark(DWORD guildID)
{

View File

@@ -45,6 +45,7 @@ class CGuildMarkManager : public singleton<CGuildMarkManager>
// SERVER
void CopyMarkIdx(char * pcBuf) const;
DWORD SaveMark(DWORD guildID, BYTE * pbMarkImage);
DWORD AllocMark(DWORD guildID); // Allocate a mark slot with default (empty) image
void DeleteMark(DWORD guildID);
void GetDiffBlocks(DWORD imgIdx, const uint32_t* crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks);

View File

@@ -16,6 +16,7 @@
#include "locale_service.h"
#include "log.h"
#include "questmanager.h"
#include "MarkManager.h"
SGuildMember::SGuildMember(LPCHARACTER ch, BYTE grade, DWORD offer_exp)
: pid(ch->GetPlayerID()), grade(grade), is_general(0), job(ch->GetJob()), level(ch->GetLevel()), offer_exp(offer_exp), name(ch->GetName())
@@ -113,6 +114,9 @@ CGuild::CGuild(TGuildCreateParameter & cp)
AddMember(&p);
*/
RequestAddMember(cp.master, GUILD_LEADER_GRADE);
// Allocate a mark slot for the new guild
CGuildMarkManager::instance().AllocMark(GetID());
}
void CGuild::Initialize()
@@ -375,25 +379,23 @@ void CGuild::SendListOneToAll(LPCHARACTER ch)
void CGuild::SendListOneToAll(DWORD pid)
{
TPacketGCGuild pack;
pack.header = HEADER_GC_GUILD;
pack.size = sizeof(TPacketGCGuild);
pack.subheader = GUILD_SUBHEADER_GC_LIST;
pack.size += sizeof(TGuildMemberPacketData);
char c[CHARACTER_NAME_MAX_LEN+1];
memset(c, 0, sizeof(c));
TGuildMemberContainer::iterator cit = m_member.find(pid);
if (cit == m_member.end())
return;
TPacketGCGuild pack;
pack.header = HEADER_GC_GUILD;
pack.size = sizeof(TPacketGCGuild) + sizeof(TGuildMemberPacketData) + CHARACTER_NAME_MAX_LEN + 1;
pack.subheader = GUILD_SUBHEADER_GC_LIST;
char szName[CHARACTER_NAME_MAX_LEN + 1];
memset(szName, 0, sizeof(szName));
strlcpy(szName, cit->second.name.c_str(), sizeof(szName));
for (TGuildMemberOnlineContainer::iterator it = m_memberOnline.begin(); it!= m_memberOnline.end(); ++it)
{
LPDESC d = (*it)->GetDesc();
if (!d)
if (!d)
continue;
TGuildMemberPacketData p;
@@ -404,12 +406,11 @@ void CGuild::SendListOneToAll(DWORD pid)
p.level = cit->second.level;
p.offer = cit->second.offer_exp;
p.name_flag = 1;
strlcpy(p.name, cit->second.name.c_str(), sizeof(p.name));
TEMP_BUFFER buf;
buf.write(&pack, sizeof(pack));
buf.write(&p, sizeof(p));
buf.write(szName, CHARACTER_NAME_MAX_LEN + 1);
d->Packet(buf.read_peek(), buf.size());
}
}
@@ -424,7 +425,7 @@ void CGuild::SendListPacket(LPCHARACTER ch)
[
...
name_flag 1 - 이름을 보내느냐 안보내느냐
name CHARACTER_NAME_MAX_LEN+1
name CHARACTER_NAME_MAX_LEN+1 (only if name_flag is 1)
] * Count
*/
@@ -437,10 +438,11 @@ void CGuild::SendListPacket(LPCHARACTER ch)
pack.size = sizeof(TPacketGCGuild);
pack.subheader = GUILD_SUBHEADER_GC_LIST;
pack.size += sizeof(TGuildMemberPacketData) * m_member.size();
// Each member: struct + name (always sent with name_flag=1)
pack.size += (sizeof(TGuildMemberPacketData) + CHARACTER_NAME_MAX_LEN + 1) * m_member.size();
TEMP_BUFFER buf;
buf.write(&pack,sizeof(pack));
buf.write(&pack, sizeof(pack));
for (TGuildMemberContainer::iterator it = m_member.begin(); it != m_member.end(); ++it)
{
@@ -452,11 +454,16 @@ void CGuild::SendListPacket(LPCHARACTER ch)
p.level = it->second.level;
p.offer = it->second.offer_exp;
p.name_flag = 1;
strlcpy(p.name, it->second.name.c_str(), sizeof(p.name));
buf.write(&p, sizeof(p));
if ( test_server )
sys_log(0 ,"name %s job %d ", it->second.name.c_str(), it->second.job );
// Send name separately after the struct
char szName[CHARACTER_NAME_MAX_LEN + 1];
memset(szName, 0, sizeof(szName));
strlcpy(szName, it->second.name.c_str(), sizeof(szName));
buf.write(szName, sizeof(szName));
if (test_server)
sys_log(0, "name %s job %d", it->second.name.c_str(), it->second.job);
}
d->Packet(buf.read_peek(), buf.size());
@@ -470,7 +477,6 @@ void CGuild::SendListPacket(LPCHARACTER ch)
{
SendLoginPacket(ch, *it);
}
}
void CGuild::SendLoginPacket(LPCHARACTER ch, LPCHARACTER chLogin)
@@ -1407,7 +1413,7 @@ void CGuild::SendSkillInfoPacket(LPCHARACTER ch) const
TPacketGCGuild pack;
pack.header = HEADER_GC_GUILD;
pack.size = sizeof(pack) + 6 + GUILD_SKILL_COUNT;
pack.size = sizeof(pack) + 5 + GUILD_SKILL_COUNT; // 1 (skill_point) + GUILD_SKILL_COUNT (abySkill) + 2 (power) + 2 (max_power)
pack.subheader = GUILD_SUBHEADER_GC_SKILL_INFO;
d->BufferedPacket(&pack, sizeof(pack));

View File

@@ -48,7 +48,7 @@ typedef struct SGuildMember
#pragma pack(1)
typedef struct SGuildMemberPacketData
{
{
uint32_t pid;
uint8_t grade;
uint8_t is_general;
@@ -56,7 +56,7 @@ typedef struct SGuildMemberPacketData
uint8_t level;
uint32_t offer;
uint8_t name_flag;
char name[CHARACTER_NAME_MAX_LEN+1];
// Note: name is sent separately after this struct if name_flag is set
} TGuildMemberPacketData;
typedef struct packet_guild_sub_info

View File

@@ -17,6 +17,7 @@ enum
};
void LoginFailure(LPDESC d, const char * c_pszStatus);
void BroadcastGuildMarkUpdate(DWORD dwGuildID, WORD wImgIdx);
class CInputProcessor
@@ -345,6 +346,7 @@ class CInputP2P : public CInputProcessor
void IamAwake(LPDESC d, const char * c_pData);
void MessengerRequestAdd(const char* c_pData);
void MessengerResponse(const char* c_pData);
void GuildMarkUpdate(const char * c_pData);
protected:
CPacketInfoGG m_packetInfoGG;

View File

@@ -27,6 +27,7 @@
#include "log.h"
#include "horsename_manager.h"
#include "MarkManager.h"
#include "p2p.h"
static void _send_bonus_info(LPCHARACTER ch)
{
@@ -931,27 +932,22 @@ void CInputLogin::GuildMarkUpload(LPDESC d, const char* c_pData)
else
markID = rkMarkMgr.SaveMark(p->gid, p->image);
// Broadcast mark update to all connected game clients
// Broadcast mark update to all game cores via P2P, which will then broadcast to their clients
if (markID != CGuildMarkManager::INVALID_MARK_ID)
{
WORD imgIdx = static_cast<WORD>(markID / CGuildMarkImage::MARK_TOTAL_COUNT);
TPacketGCMarkUpdate packet;
packet.header = HEADER_GC_MARK_UPDATE;
packet.guildID = p->gid;
packet.imgIdx = imgIdx;
// Send P2P packet to all other game cores
TPacketGGMarkUpdate p2pPacket;
p2pPacket.bHeader = HEADER_GG_MARK_UPDATE;
p2pPacket.dwGuildID = p->gid;
p2pPacket.wImgIdx = imgIdx;
P2P_MANAGER::instance().Send(&p2pPacket, sizeof(p2pPacket));
const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
for (DESC_MANAGER::DESC_SET::const_iterator it = c_set_desc.begin(); it != c_set_desc.end(); ++it)
{
LPDESC pkDesc = *it;
if (pkDesc && pkDesc->GetCharacter())
{
pkDesc->Packet(&packet, sizeof(packet));
}
}
// Also broadcast to clients connected to this core (mark server) using the same logic
BroadcastGuildMarkUpdate(p->gid, imgIdx);
sys_log(0, "MARK_SERVER: GuildMarkUpload: Broadcast mark update for guild %u, imgIdx %u", p->gid, imgIdx);
sys_log(0, "MARK_SERVER: GuildMarkUpload: Broadcast mark update for guild %u, imgIdx %u via P2P", p->gid, imgIdx);
}
}

View File

@@ -457,6 +457,34 @@ void CInputP2P::IamAwake(LPDESC d, const char * c_pData)
sys_log(0, "P2P Awakeness check from %s. My P2P connection number is %d. and details...\n%s", d->GetHostName(), P2P_MANAGER::instance().GetDescCount(), hostNames.c_str());
}
// Shared function to broadcast mark update to all clients on this core
void BroadcastGuildMarkUpdate(DWORD dwGuildID, WORD wImgIdx)
{
TPacketGCMarkUpdate packet;
packet.header = HEADER_GC_MARK_UPDATE;
packet.guildID = dwGuildID;
packet.imgIdx = wImgIdx;
const DESC_MANAGER::DESC_SET & c_set_desc = DESC_MANAGER::instance().GetClientSet();
for (DESC_MANAGER::DESC_SET::const_iterator it = c_set_desc.begin(); it != c_set_desc.end(); ++it)
{
LPDESC pkDesc = *it;
if (pkDesc && pkDesc->GetCharacter())
{
pkDesc->Packet(&packet, sizeof(packet));
}
}
sys_log(0, "BroadcastGuildMarkUpdate: guild %u, imgIdx %u, sent to %zu clients",
dwGuildID, wImgIdx, c_set_desc.size());
}
void CInputP2P::GuildMarkUpdate(const char * c_pData)
{
TPacketGGMarkUpdate * p = (TPacketGGMarkUpdate *) c_pData;
BroadcastGuildMarkUpdate(p->dwGuildID, p->wImgIdx);
}
int CInputP2P::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
if (test_server)
@@ -581,6 +609,10 @@ int CInputP2P::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
case HEADER_GG_CHECK_AWAKENESS:
IamAwake(d, c_pData);
break;
case HEADER_GG_MARK_UPDATE:
GuildMarkUpdate(c_pData);
break;
}
return (iExtraLen);

View File

@@ -315,6 +315,7 @@ enum
HEADER_GG_MONARCH_TRANSFER = 27,
HEADER_GG_CHECK_AWAKENESS = 29,
HEADER_GG_MARK_UPDATE = 30,
};
#pragma pack(1)
@@ -516,6 +517,13 @@ typedef struct SPacketGGBlockChat
int32_t lBlockDuration;
} TPacketGGBlockChat;
typedef struct packet_gg_mark_update
{
uint8_t bHeader;
uint32_t dwGuildID;
uint16_t wImgIdx;
} TPacketGGMarkUpdate;
/* 클라이언트 측에서 보내는 패킷 */
typedef struct command_text

View File

@@ -267,6 +267,7 @@ CPacketInfoGG::CPacketInfoGG()
Set(HEADER_GG_MONARCH_NOTICE, sizeof(TPacketGGMonarchNotice), "MonarchNotice", false);
Set(HEADER_GG_MONARCH_TRANSFER, sizeof(TPacketMonarchGGTransfer), "MonarchTransfer", false);
Set(HEADER_GG_CHECK_AWAKENESS, sizeof(TPacketGGCheckAwakeness), "CheckAwakeness", false);
Set(HEADER_GG_MARK_UPDATE, sizeof(TPacketGGMarkUpdate), "MarkUpdate", false);
}
CPacketInfoGG::~CPacketInfoGG()