[FIX] Fix for world crash with over 1500 guilds (#4299)

* Fix for world crash with over 1500 guilds

There was an existing issue with certain clients (RoF2) if there were more than 1500 guilds.  This also enhances the loading of guilds in both world and zone for performance if there are large number of guilds as RoF2 will support 1500+ guilds.

* Safely access permissions map

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
Mitch Freeman
2024-05-09 02:53:36 -03:00
committed by GitHub
parent 257935d33a
commit d1c7e45437
14 changed files with 210 additions and 136 deletions
+20 -43
View File
@@ -1401,58 +1401,35 @@ namespace RoF2
ENCODE(OP_GuildsList)
{
EQApplicationPacket *in = *p;
*p = nullptr;
*p = nullptr;
uint32 NumberOfGuilds = in->size / 64;
uint32 PacketSize = 68; // 64 x 0x00 + a uint32 that I am guessing is the highest guild ID in use.
GuildsListMessaging_Struct glms{};
EQ::Util::MemoryStreamReader ss(reinterpret_cast<char *>(in->pBuffer), in->size);
cereal::BinaryInputArchive ar(ss);
ar(glms);
unsigned char *__emu_buffer = in->pBuffer;
auto packet_size = 64 + 4 + glms.guild_detail.size() * 4 + glms.string_length;
auto buffer = new uchar[packet_size];
auto buf_pos = buffer;
char *InBuffer = (char *)__emu_buffer;
memset(buf_pos, 0, 64);
buf_pos += 64;
uint32 HighestGuildID = 0;
VARSTRUCT_ENCODE_TYPE(uint32, buf_pos, glms.no_of_guilds);
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
if (InBuffer[0])
{
PacketSize += (5 + strlen(InBuffer));
HighestGuildID += 1;
for (auto const &g: glms.guild_detail) {
if (g.guild_id < RoF2::constants::MAX_GUILD_ID) {
VARSTRUCT_ENCODE_TYPE(uint32, buf_pos, g.guild_id);
strn0cpy((char *) buf_pos, g.guild_name.c_str(), g.guild_name.length() + 1);
buf_pos += g.guild_name.length() + 1;
}
InBuffer += 64;
}
PacketSize++; // Appears to be an extra 0x00 at the very end.
auto outapp = new EQApplicationPacket(OP_GuildsList);
outapp->size = packet_size;
outapp->pBuffer = buffer;
in->size = PacketSize;
in->pBuffer = new unsigned char[in->size];
InBuffer = (char *)__emu_buffer;
char *OutBuffer = (char *)in->pBuffer;
// Init the first 64 bytes to zero, as per live.
//
memset(OutBuffer, 0, 64);
OutBuffer += 64;
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, HighestGuildID);
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
if (InBuffer[0])
{
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, i - 1);
VARSTRUCT_ENCODE_STRING(OutBuffer, InBuffer);
}
InBuffer += 64;
}
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0x00);
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildTributeDonateItem)