This commit is contained in:
Chris Miles 2025-06-12 02:12:46 -05:00
parent 6be59b229a
commit e7594fcfbd
2 changed files with 20 additions and 18 deletions

View File

@ -209,7 +209,8 @@ public:
Timer m_mob_check_moving_timer; Timer m_mob_check_moving_timer;
uint16 m_last_wearchange_race_id = 0; uint16 m_last_wearchange_race_id = 0;
std::unordered_map<uint32_t, uint64_t> m_last_seen_wearchange; // client_id -> slot_id -> key
std::unordered_map<uint32_t, std::unordered_map<uint8_t, uint64_t>> m_last_seen_wearchange;
// Bot attack flag // Bot attack flag
Timer bot_attack_flag_timer; Timer bot_attack_flag_timer;

View File

@ -378,8 +378,8 @@ void Mob::SendArmorAppearance(Client *one_client)
void Mob::SendWearChange(uint8 material_slot, Client *one_client) void Mob::SendWearChange(uint8 material_slot, Client *one_client)
{ {
static auto packet = EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); auto packet = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
auto w = reinterpret_cast<WearChange_Struct*>(packet.pBuffer); auto w = reinterpret_cast<WearChange_Struct*>(packet->pBuffer);
w->spawn_id = GetID(); w->spawn_id = GetID();
w->material = static_cast<uint32>(GetEquipmentMaterial(material_slot)); w->material = static_cast<uint32>(GetEquipmentMaterial(material_slot));
@ -404,33 +404,32 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client)
// it includes spawn_id, material, elite_material, hero_forge_model, wear_slot_id, and color // it includes spawn_id, material, elite_material, hero_forge_model, wear_slot_id, and color
// we send an enormous amount of wearchange packets in brute-force fashion and this is a low cost way to deduplicate them // we send an enormous amount of wearchange packets in brute-force fashion and this is a low cost way to deduplicate them
// we could remove all the extra wearchanges at the expense of tracing down intermittent visual bugs over a long time // we could remove all the extra wearchanges at the expense of tracing down intermittent visual bugs over a long time
auto build_key = [&](const WearChange_Struct& s) -> uint64_t auto build_key = [&](const WearChange_Struct& s) -> uint64_t {
{
uint64_t key = 0; uint64_t key = 0;
// Bit layout: key |= static_cast<uint64_t>(s.material & 0xFFF) << 0; // 12 bits
// Bits 011 : material (12 bits) key |= static_cast<uint64_t>(s.elite_material & 0x1) << 12; // 1 bit
// Bits 12 : elite_material (1 bit) key |= static_cast<uint64_t>(s.hero_forge_model & 0xFFFFF) << 13; // 20 bits
// Bits 1332 : hero_forge_model (20 bits) key |= static_cast<uint64_t>(GetRace() & 0xFFFF) << 33; // 16 bits
// Bits 3348 : race (16 bits)
// Bits 4956 : wear_slot_id (8 bits) // Optional: Fold in color for appearance differences
key |= static_cast<uint64_t>(s.material & 0xFFF) << 0; uint8_t folded_color = static_cast<uint8_t>(
key |= static_cast<uint64_t>(s.elite_material & 0x1) << 12; (s.color.Color * 17ull) & 0xFF
key |= static_cast<uint64_t>(s.hero_forge_model & 0xFFFFF) << 13; );
key |= static_cast<uint64_t>(GetRace() & 0xFFFF) << 33; key |= static_cast<uint64_t>(folded_color) << 49;
key |= static_cast<uint64_t>(s.wear_slot_id & 0xFF) << 49;
return key; return key;
}; };
auto dedupe_key = build_key(*w); auto dedupe_key = build_key(*w);
auto send_if_changed = [&](Client* client) { auto send_if_changed = [&](Client* client) {
auto& last_key = m_last_seen_wearchange[client->GetID()]; auto& last_key = m_last_seen_wearchange[client->GetID()][material_slot];
if (last_key == dedupe_key) { if (last_key == dedupe_key) {
return; return;
} }
last_key = dedupe_key; last_key = dedupe_key;
client->QueuePacket(&packet, true, Client::CLIENT_CONNECTED); client->QueuePacket(packet, true, Client::CLIENT_CONNECTED);
}; };
if (one_client) { if (one_client) {
@ -443,6 +442,8 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client)
} }
} }
} }
safe_delete(packet);
} }
void Mob::SendTextureWC( void Mob::SendTextureWC(