diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 08334a897..75a53dd00 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -1850,3 +1850,39 @@ std::map ClientList::GetGuildClientsWithTributeOptIn( } return guild_members; } + +#include + +std::vector ClientList::GetGuildZoneServers(uint32 guild_id) +{ + std::vector zone_server_ids; + std::unordered_set seen_ids; + + LinkedListIterator iterator(clientlist); + + iterator.Reset(); + while (iterator.MoreElements()) { + ClientListEntry *cle = iterator.GetData(); + + if (cle->Online() != CLE_Status::InZone) { + iterator.Advance(); + continue; + } + + if (!cle->Server()) { + iterator.Advance(); + continue; + } + + if (cle->GuildID() == guild_id) { + uint32_t id = cle->Server()->GetID(); + if (seen_ids.insert(id).second) { + zone_server_ids.emplace_back(id); + } + } + + iterator.Advance(); + } + + return zone_server_ids; +} diff --git a/world/clientlist.h b/world/clientlist.h index 11e45ceb8..8fb6958a7 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -60,6 +60,7 @@ public: void CLCheckStale(); void CLEKeepAlive(uint32 numupdates, uint32* wid); void CLEAdd(uint32 login_server_id, const char* login_server_name, const char* login_name, const char* login_key, int16 world_admin = AccountStatus::Player, uint32 ip_address = 0, uint8 is_local=0); + std::vector GetGuildZoneServers(uint32 guild_id); void UpdateClientGuild(uint32 char_id, uint32 guild_id); bool IsAccountInGame(uint32 iLSID); diff --git a/world/wguild_mgr.cpp b/world/wguild_mgr.cpp index 03b7204fb..4bacceb32 100644 --- a/world/wguild_mgr.cpp +++ b/world/wguild_mgr.cpp @@ -50,7 +50,7 @@ void WorldGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, s->motd_change = motd; s->rank_change = rank; s->relation_change = relation; - zoneserver_list.SendPacket(pack); + zoneserver_list.SendPacketToZonesWithGuild(guild_id, pack); safe_delete(pack); } @@ -61,7 +61,7 @@ void WorldGuildManager::SendCharRefresh(uint32 old_guild_id, uint32 guild_id, ui s->guild_id = guild_id; s->old_guild_id = old_guild_id; s->char_id = charid; - zoneserver_list.SendPacket(pack); + zoneserver_list.SendPacketToZonesWithGuild(guild_id, pack); safe_delete(pack); } @@ -70,7 +70,7 @@ void WorldGuildManager::SendGuildDelete(uint32 guild_id) { auto pack = new ServerPacket(ServerOP_DeleteGuild, sizeof(ServerGuildID_Struct)); ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer; s->guild_id = guild_id; - zoneserver_list.SendPacket(pack); + zoneserver_list.SendPacketToZonesWithGuild(guild_id, pack); safe_delete(pack); } @@ -85,15 +85,14 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer; LogGuilds("Received and broadcasting guild refresh for [{}], changes: name=[{}], motd=[{}], rank=d, relation=[{}]", s->guild_id, s->name_change, s->motd_change, s->rank_change, s->relation_change); - //broadcast this packet to all zones. - zoneserver_list.SendPacket(pack); - //preform a local refresh. if(!RefreshGuild(s->guild_id)) { - LogGuilds("Unable to preform local refresh on guild [{}]", s->guild_id); - //can we do anything? + BaseGuildManager::RefreshGuild(s->guild_id); } + //broadcast this packet to all zones. + zoneserver_list.SendPacketToZonesWithGuild(s->guild_id, pack); + break; } @@ -108,7 +107,7 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { //broadcast this update to any zone with a member in this guild. //because im sick of this not working, sending it to all zones, just spends a bit more bandwidth. - zoneserver_list.SendPacket(pack); + zoneserver_list.SendPacketToZonesWithGuild(s->guild_id, pack); break; } @@ -147,7 +146,7 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { auto s = (ServerGuildID_Struct *)pack->pBuffer; RefreshGuild(s->guild_id); - zoneserver_list.SendPacket(pack); + zoneserver_list.SendPacketToZonesWithGuild(s->guild_id, pack); break; } case ServerOP_GuildPermissionUpdate: @@ -179,7 +178,7 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { sg->function_value ); - zoneserver_list.SendPacketToBootedZones(pack); + zoneserver_list.SendPacketToZonesWithGuild(sg->guild_id, pack); } else { LogError("World Received ServerOP_GuildPermissionUpdate for guild [{}] function id {} with value of {} but guild could not be found.", @@ -213,7 +212,7 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { rnc->rank, rnc->rank_name ); - zoneserver_list.SendPacketToBootedZones(pack); + zoneserver_list.SendPacketToZonesWithGuild(rnc->guild_id, pack); } else { LogError("World Received ServerOP_GuildRankNameChange from zone for guild [{}] rank id {} with new name of {} but could not find guild.", @@ -230,13 +229,13 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { case ServerOP_GuildChannel: case ServerOP_GuildURL: case ServerOP_GuildMemberRemove: - case ServerOP_GuildSendGuildList: case ServerOP_GuildMembersList: { - zoneserver_list.SendPacketToBootedZones(pack); + auto in = (ServerOP_GuildMessage_Struct *) pack->pBuffer; + zoneserver_list.SendPacketToZonesWithGuild(in->guild_id, pack); break; } - case ServerOP_GuildMemberAdd: + case ServerOP_GuildMemberAdd: { auto in = (ServerOP_GuildMessage_Struct *)pack->pBuffer; auto guild = GetGuildByGuildID(in->guild_id); @@ -244,9 +243,15 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { BaseGuildManager::RefreshGuild(in->guild_id); } - zoneserver_list.SendPacketToBootedZones(pack); + zoneserver_list.SendPacketToZonesWithGuild(in->guild_id, pack); break; } + case ServerOP_GuildSendGuildList: { + auto in = (ServerOP_GuildMessage_Struct *) pack->pBuffer; + zoneserver_list.SendPacketToBootedZones(pack); + break; + } + default: LogGuilds("Unknown packet {:#04x} received from zone??", pack->opcode); break; @@ -451,6 +456,6 @@ void WorldGuildManager::SendGuildTributeFavorAndTimer(uint32 guild_id, uint32 fa data->tribute_timer = time; data->trophy_timer = 0; - zoneserver_list.SendPacketToBootedZones(sp); + zoneserver_list.SendPacketToZonesWithGuild(guild_id, sp); safe_delete(sp) } diff --git a/world/zonelist.cpp b/world/zonelist.cpp index fdf8dcf39..6f429f640 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -36,11 +36,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "shared_task_manager.h" #include "dynamic_zone_manager.h" #include "ucs.h" +#include "clientlist.h" extern uint32 numzones; extern EQ::Random emu_random; extern WebInterfaceList web_interface; extern SharedTaskManager shared_task_manager; +extern ClientList client_list; volatile bool UCSServerAvailable_ = false; void CatchSignal(int sig_num); @@ -871,6 +873,20 @@ bool ZSList::SendPacketToBootedZones(ServerPacket* pack) return true; } +bool ZSList::SendPacketToZonesWithGuild(uint32 guild_id, ServerPacket* pack) +{ + auto servers = client_list.GetGuildZoneServers(guild_id); + for (auto const& z : zone_server_list) { + for (auto const& server_id : servers) { + if (z->GetID() == server_id && z->GetZoneID() > 0) { + z->SendPacket(pack); + } + } + } + + return true; +} + void ZSList::SendServerReload(ServerReload::Type type, uchar *packet) { static auto pack = ServerPacket(ServerOP_ServerReloadRequest, sizeof(ServerReload::Request)); diff --git a/world/zonelist.h b/world/zonelist.h index aa59b1fd6..d12b247ae 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -29,6 +29,7 @@ public: bool SendPacket(ServerPacket *pack); bool SendPacket(uint32 zoneid, ServerPacket *pack); bool SendPacket(uint32 zoneid, uint16 instanceid, ServerPacket *pack); + bool SendPacketToZonesWithGuild(uint32 guild_id, ServerPacket *pack); bool SendPacketToBootedZones(ServerPacket* pack); bool SetLockedZone(uint16 iZoneID, bool iLock); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 8c535cedd..9716bc7c7 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1510,7 +1510,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { guild->tribute.timer.Disable(); - zoneserver_list.SendPacketToBootedZones(pack); + zoneserver_list.SendPacketToZonesWithGuild(data->guild_id, pack); } break; } @@ -1553,7 +1553,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { guild_mgr.UpdateDbGuildFavor(data->guild_id, data->favor); guild_mgr.UpdateDbTributeTimeRemaining(data->guild_id, data->time_remaining); - zoneserver_list.SendPacketToBootedZones(pack); + zoneserver_list.SendPacketToZonesWithGuild(data->guild_id, pack); } break; } @@ -1587,7 +1587,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { data->time_remaining = in->time_remaining; strn0cpy(data->player_name, in->player_name, sizeof(data->player_name)); - zoneserver_list.SendPacketToBootedZones(out); + zoneserver_list.SendPacketToZonesWithGuild(in->guild_id, out); safe_delete(out); } break; @@ -1610,7 +1610,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { out->tribute_id_2_tier = guild->tribute.id_2_tier; out->time_remaining = guild_mgr.GetGuildTributeTimeRemaining(in->guild_id); - zoneserver_list.SendPacketToBootedZones(sp); + zoneserver_list.SendPacketToZonesWithGuild(in->guild_id, sp); safe_delete(sp); } @@ -1630,7 +1630,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { out->tribute_timer = guild_mgr.GetGuildTributeTimeRemaining(in->guild_id); out->trophy_timer = 0; - zoneserver_list.SendPacketToBootedZones(sp); + zoneserver_list.SendPacketToZonesWithGuild(in->guild_id, sp); safe_delete(sp); } @@ -1654,7 +1654,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { out->member_time = in->member_time; strn0cpy(out->player_name, in->player_name, sizeof(out->player_name)); - zoneserver_list.SendPacketToBootedZones(sp); + zoneserver_list.SendPacketToZonesWithGuild(out->guild_id, sp); safe_delete(sp) } break; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5ed9f4ae4..430d02559 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -7980,7 +7980,7 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app) } SetGuildID(new_guild_id); - SendGuildList(); + UpdateWho(); guild_mgr.MemberAdd(new_guild_id, CharacterID(), GetLevel(), GetClass(), GUILD_LEADER, GetZoneID(), GetName()); guild_mgr.SendGuildRefresh(new_guild_id, true, true, true, true); guild_mgr.SendToWorldSendGuildList(); @@ -8149,7 +8149,7 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) if (!invitee) { Message( Chat::Red, - "Prospective guild member %s must be in zone to preform guild operations on them.", + "Prospective guild member %s must be in zone to perform guild operations on them.", gc->othername ); return; diff --git a/zone/guild.cpp b/zone/guild.cpp index 40bddc2e6..9c48b5e3e 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -195,7 +195,7 @@ void Client::SendGuildList() std::stringstream ss; cereal::BinaryOutputArchive ar(ss); - ar(guilds_list); + { ar(guilds_list); } uint32 packet_size = ss.str().length();