[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)
+1
View File
@@ -271,6 +271,7 @@ namespace RoF2
const size_t CHARACTER_CREATION_LIMIT = 12;
const size_t SAY_LINK_BODY_SIZE = 56;
const uint32 MAX_GUILD_ID = 50000;
} /*constants*/
+22
View File
@@ -748,6 +748,28 @@ namespace Titanium
FINISH_ENCODE();
}
ENCODE(OP_GuildsList)
{
EQApplicationPacket* in = *p;
*p = nullptr;
GuildsListMessaging_Struct glms{};
EQ::Util::MemoryStreamReader ss(reinterpret_cast<char *>(in->pBuffer), in->size);
cereal::BinaryInputArchive ar(ss);
ar(glms);
auto outapp = new EQApplicationPacket(OP_GuildsList, sizeof(structs::GuildsList_Struct));
auto out = (structs::GuildsList_Struct *) outapp->pBuffer;
for (auto const& g : glms.guild_detail) {
if (g.guild_id < Titanium::constants::MAX_GUILD_ID) {
strn0cpy(out->Guilds[g.guild_id].name, g.guild_name.c_str(), sizeof(out->Guilds[g.guild_id].name));
}
}
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberAdd)
{
ENCODE_LENGTH_EXACT(GuildMemberAdd_Struct)
+1
View File
@@ -287,6 +287,7 @@ namespace Titanium
const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER
const size_t SAY_LINK_BODY_SIZE = 45;
const uint32 MAX_GUILD_ID = 1500;
} /*constants*/
+1
View File
@@ -45,6 +45,7 @@ E(OP_Emote)
E(OP_FormattedMessage)
E(OP_GroundSpawn)
E(OP_SetGuildRank)
E(OP_GuildsList)
E(OP_GuildMemberLevelUpdate)
E(OP_GuildMemberList)
E(OP_GuildMemberAdd)
+22 -38
View File
@@ -1182,53 +1182,37 @@ namespace UF
ENCODE(OP_GuildsList)
{
EQApplicationPacket *in = *p;
EQApplicationPacket* in = *p;
*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;
char *InBuffer = (char *)__emu_buffer;
uint32 actual_no_guilds = 0;
auto packet_size = 64 + 4 + glms.guild_detail.size() * 4 + glms.string_length;
auto buffer = new uchar[packet_size];
auto buf_pos = buffer;
for (unsigned int i = 0; i < NumberOfGuilds; ++i)
{
if (InBuffer[0])
{
PacketSize += (5 + strlen(InBuffer));
actual_no_guilds++;
memset(buf_pos, 0, 64);
buf_pos += 64;
VARSTRUCT_ENCODE_TYPE(uint32, buf_pos, glms.no_of_guilds);
for (auto const& g : glms.guild_detail) {
if (g.guild_id < UF::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.
in->size = PacketSize;
in->pBuffer = new unsigned char[in->size];
InBuffer = (char *)__emu_buffer;
char *OutBuffer = (char *)in->pBuffer;
auto outapp = new EQApplicationPacket(OP_GuildsList);
// Init the first 64 bytes to zero, as per live.
//
memset(OutBuffer, 0, 64);
OutBuffer += 64;
outapp->size = packet_size;
outapp->pBuffer = buffer;
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, actual_no_guilds);
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_GuildMemberAdd)
+1
View File
@@ -289,6 +289,7 @@ namespace UF
const size_t CHARACTER_CREATION_LIMIT = 12;
const size_t SAY_LINK_BODY_SIZE = 50;
const uint32 MAX_GUILD_ID = 50000;
} /*constants*/