Protection on group member info when updates are made

Prevents corruption in the group member pointers.. clients couldn't see each other in group lists or chat to each other depending on special conditions
This commit is contained in:
image 2020-08-30 08:29:19 -04:00
parent ee62b2ee39
commit 5bf65b9399
6 changed files with 53 additions and 26 deletions

View file

@ -2347,23 +2347,20 @@ void Entity::RemoveSafefallSpell(LuaSpell* spell){
((Player*)this)->SetPlayerControlFlag(4, 32, false);
}
void Entity::UpdateGroupMemberInfo() {
if (!group_member_info)
void Entity::UpdateGroupMemberInfo(bool inGroupMgrLock, bool groupMembersLocked) {
if (!group_member_info || group_id == 0)
return;
group_member_info->class_id = GetAdventureClass();
group_member_info->hp_max = GetTotalHP();
group_member_info->hp_current = GetHP();
group_member_info->level_max = GetLevel();
group_member_info->level_current = GetLevel();
group_member_info->name = string(GetName());
group_member_info->power_current = GetPower();
group_member_info->power_max = GetTotalPower();
group_member_info->race_id = GetRace();
if (GetZone())
group_member_info->zone = GetZone()->GetZoneDescription();
else
group_member_info->zone = "Unknown";
if(!inGroupMgrLock)
world.GetGroupManager()->GroupLock(__FUNCTION__, __LINE__);
PlayerGroup* group = world.GetGroupManager()->GetGroup(group_id);
if (group)
group->UpdateGroupMemberInfo(this, groupMembersLocked);
if(!inGroupMgrLock)
world.GetGroupManager()->ReleaseGroupLock(__FUNCTION__, __LINE__);
}
#include "WorldDatabase.h"

View file

@ -793,7 +793,7 @@ public:
GroupMemberInfo* GetGroupMemberInfo() { return group_member_info; }
void SetGroupMemberInfo(GroupMemberInfo* info) { group_member_info = info; }
void UpdateGroupMemberInfo();
void UpdateGroupMemberInfo(bool inGroupMgrLock=false, bool groupMembersLocked=false);
void CustomizeAppearance(PacketStruct* packet);

View file

@ -62,10 +62,10 @@ bool PlayerGroup::AddMember(Entity* member) {
gmi->client = 0;
member->SetGroupMemberInfo(gmi);
member->UpdateGroupMemberInfo();
member->group_id = gmi->group_id;
MGroupMembers.writelock();
m_members.push_back(gmi);
member->UpdateGroupMemberInfo(true, true);
MGroupMembers.releasewritelock();
SendGroupUpdate();
@ -257,14 +257,15 @@ void PlayerGroupManager::NewGroup(Entity* leader) {
// Create a new group with the valid ID we got from above
PlayerGroup* new_group = new PlayerGroup(m_nextGroupID);
// Add the new group to the list (need to do this first, AddMember needs ref to the PlayerGroup ptr -> UpdateGroupMemberInfo)
m_groups[m_nextGroupID] = new_group;
// Add the leader to the group
new_group->AddMember(leader);
leader->GetGroupMemberInfo()->leader = true;
// Add the new group to the list
m_groups[m_nextGroupID] = new_group;
MGroups.releasewritelock(__FUNCTION__, __LINE__);
}
@ -767,4 +768,32 @@ void PlayerGroup::RemoveClientReference(Client* remove) {
}
}
MGroupMembers.releasewritelock();
}
void PlayerGroup::UpdateGroupMemberInfo(Entity* ent, bool groupMembersLocked) {
Player* player = (Player*)ent;
if (!player || !player->GetGroupMemberInfo())
return;
if(!groupMembersLocked)
MGroupMembers.writelock();
GroupMemberInfo* group_member_info = player->GetGroupMemberInfo();
player->GetGroupMemberInfo()->class_id = player->GetAdventureClass();
group_member_info->hp_max = player->GetTotalHP();
group_member_info->hp_current = player->GetHP();
group_member_info->level_max = player->GetLevel();
group_member_info->level_current = player->GetLevel();
group_member_info->name = string(player->GetName());
group_member_info->power_current = player->GetPower();
group_member_info->power_max = player->GetTotalPower();
group_member_info->race_id = player->GetRace();
if (player->GetZone())
group_member_info->zone = player->GetZone()->GetZoneDescription();
else
group_member_info->zone = "Unknown";
if(!groupMembersLocked)
MGroupMembers.releasewritelock();
}

View file

@ -84,6 +84,7 @@ public:
void MakeLeader(Entity* new_leader);
void RemoveClientReference(Client* remove);
void UpdateGroupMemberInfo(Entity* ent, bool groupMembersLocked=false);
Mutex MGroupMembers; // Mutex for the group members
private:

View file

@ -1499,7 +1499,7 @@ void World::RejoinGroup(Client* client, int32 group_id){
info->member = client->GetPlayer();
client->GetPlayer()->SetGroup(group);
client->GetPlayer()->SetGroupMemberInfo(info);
client->GetPlayer()->UpdateGroupMemberInfo();
client->GetPlayer()->UpdateGroupMemberInfo(true, true);
LogWrite(PLAYER__DEBUG, 0, "Player", "Identified group match for player %s to group id %u", name.c_str(), group_id);
match = true;
break;

View file

@ -1338,6 +1338,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
if (!IsReadyForSpawns())
SetReadyForSpawns(true);
SendCharInfo();
world.RejoinGroup(this, rejoin_group_id);
pos_update.Start();
quest_pos_timer.Start();
break;
@ -3513,9 +3514,6 @@ void Client::Zone(ZoneServer* new_zone, bool set_coords) {
return;
}
// block out the member info for the group
TempRemoveGroup();
client_zoning = true;
LogWrite(CCLIENT__DEBUG, 0, "Client", "%s: Setting player Resurrecting to 'true'", __FUNCTION__);
player->SetResurrecting(true);
@ -3543,6 +3541,9 @@ void Client::Zone(ZoneServer* new_zone, bool set_coords) {
world.GetGroupManager()->SendGroupUpdate(player->GetGroupMemberInfo()->group_id, this);
}
// block out the member info for the group
TempRemoveGroup();
UpdateTimeStampFlag(ZONE_UPDATE_FLAG);
if (set_coords)
@ -8703,7 +8704,6 @@ bool Client::HandleNewLogin(int32 account_id, int32 access_code)
new_client_login = true;
GetCurrentZone()->AddClient(this); //add to zones client list
world.RejoinGroup(this, rejoin_group_id);
zone_list.AddClientToMap(player->GetName(), this);
}
else {