SetQuestsRequired is now mutex protected, trying to prevent crash on deconstructor

This commit is contained in:
image 2020-08-30 17:48:46 -04:00
parent 4e7b684db3
commit a41aa0fa6d
6 changed files with 30 additions and 15 deletions

View file

@ -47,7 +47,7 @@ public:
new_spawn->SetAttemptsPerHarvest(num_attempts_per_harvest);
new_spawn->SetGroundSpawnEntryID(groundspawn_id);
new_spawn->SetCollectionSkill(collection_skill.c_str());
new_spawn->SetQuestsRequired(GetQuestsRequired());
SetQuestsRequired(new_spawn);
new_spawn->forceMapCheck = forceMapCheck;
return new_spawn;
}

View file

@ -73,7 +73,7 @@ NPC::NPC(NPC* old_npc){
SetTotalPowerBase(old_npc->GetTotalPowerBase());
faction_id = old_npc->faction_id;
movement_interrupted = false;
SetQuestsRequired(old_npc->GetQuestsRequired());
old_npc->SetQuestsRequired(this);
SetTransporterID(old_npc->GetTransporterID());
SetAttackType(old_npc->GetAttackType());

View file

@ -87,7 +87,7 @@ Object* Object::Copy(){
new_spawn->SetTotalPower(GetTotalPower());
new_spawn->SetHP(GetHP());
new_spawn->SetPower(GetPower());
new_spawn->SetQuestsRequired(GetQuestsRequired());
SetQuestsRequired(new_spawn);
new_spawn->SetTransporterID(GetTransporterID());
new_spawn->SetDeviceID(GetDeviceID());
new_spawn->SetSoundsDisabled(IsSoundsDisabled());

View file

@ -113,6 +113,7 @@ Spawn::Spawn(){
pickup_item_id = 0;
pickup_unique_item_id = 0;
disable_sounds = false;
has_quests_required = false;
}
Spawn::~Spawn(){
@ -125,6 +126,8 @@ Spawn::~Spawn(){
for(int32 i=0;i<secondary_command_list.size();i++){
safe_delete(secondary_command_list[i]);
}
secondary_command_list.clear();
RemoveSpawnFromGroup();
if (MMovementLocations)
MMovementLocations->writelock(__FUNCTION__, __LINE__);
@ -142,13 +145,19 @@ Spawn::~Spawn(){
MMovementLoop.lock();
for (int32 i = 0; i < movement_loop.size(); i++)
safe_delete(movement_loop.at(i));
movement_loop.clear();
MMovementLoop.unlock();
m_requiredHistory.writelock(__FUNCTION__, __LINE__);
required_history.clear();
m_requiredHistory.releasewritelock(__FUNCTION__, __LINE__);
map<int32, vector<int16>* >::iterator rq_itr;
m_requiredQuests.writelock(__FUNCTION__, __LINE__);
for (rq_itr = required_quests.begin(); rq_itr != required_quests.end(); rq_itr++){
safe_delete(rq_itr->second);
}
required_quests.clear();
m_requiredQuests.releasewritelock(__FUNCTION__, __LINE__);
// just in case to make sure data is destroyed
@ -1878,21 +1887,23 @@ bool Spawn::IsClientInMerchantLevelRange(Client* client, bool sendMessageIfDenie
return true;
}
void Spawn::SetQuestsRequired(map<int32, vector<int16>* >* quests){
if(quests){
void Spawn::SetQuestsRequired(Spawn* new_spawn){
m_requiredQuests.writelock(__FUNCTION__, __LINE__);
if(required_quests.size() > 0){
map<int32, vector<int16>* >::iterator itr;
for(itr = quests->begin(); itr != quests->end(); itr++){
for(itr = required_quests.begin(); itr != required_quests.end(); itr++){
vector<int16>* quest_steps = itr->second;
for (int32 i = 0; i < quest_steps->size(); i++)
SetQuestsRequired(itr->first, quest_steps->at(i));
new_spawn->SetQuestsRequired(itr->first, quest_steps->at(i));
}
}
m_requiredQuests.releasewritelock(__FUNCTION__, __LINE__);
}
void Spawn::SetQuestsRequired(int32 quest_id, int16 quest_step){
m_requiredQuests.writelock(__FUNCTION__, __LINE__);
if (required_quests.count(quest_id) == 0)
required_quests[quest_id] = new vector<int16>;
required_quests.insert(make_pair(quest_id, new vector<int16>));
else{
for (int32 i = 0; i < required_quests[quest_id]->size(); i++){
if (required_quests[quest_id]->at(i) == quest_step){
@ -1901,10 +1912,17 @@ void Spawn::SetQuestsRequired(int32 quest_id, int16 quest_step){
}
}
}
has_quests_required = true;
required_quests[quest_id]->push_back(quest_step);
m_requiredQuests.releasewritelock(__FUNCTION__, __LINE__);
}
bool Spawn::HasQuestsRequired()
{
return has_quests_required;
}
void Spawn::SetRequiredHistory(int32 event_id, int32 value1, int32 value2){
LUAHistory set_value;
set_value.Value = value1;
@ -1915,10 +1933,6 @@ void Spawn::SetRequiredHistory(int32 event_id, int32 value1, int32 value2){
m_requiredHistory.releasewritelock(__FUNCTION__, __LINE__);
}
map<int32, vector<int16>* >* Spawn::GetQuestsRequired(){
return &required_quests;
}
void Spawn::SetTransporterID(int32 id){
transporter_id = id;
}

View file

@ -943,10 +943,10 @@ public:
bool IsClientInMerchantLevelRange(Client* ent, bool sendMessageIfDenied = true);
int32 GetMerchantMinLevel();
int32 GetMerchantMaxLevel();
void SetQuestsRequired(map<int32, vector<int16>* >* quests);
void SetQuestsRequired(Spawn* new_spawn);
void SetQuestsRequired(int32 quest_id, int16 quest_step);
bool HasQuestsRequired();
void SetRequiredHistory(int32 event_id, int32 value1, int32 value2);
map<int32, vector<int16>* >* GetQuestsRequired();
void SetTransporterID(int32 id);
int32 GetTransporterID();
bool MeetsSpawnAccessRequirements(Player* player);
@ -1132,6 +1132,7 @@ public:
void SetSoundsDisabled(bool val) { disable_sounds = val; }
protected:
bool has_quests_required;
bool send_spawn_changes;
bool invulnerable;
bool attack_resume_needed;

View file

@ -4044,7 +4044,7 @@ void ZoneServer::SendQuestUpdates(Client* client, Spawn* spawn){
if (spawn) {
spawn->m_requiredQuests.readlock(__FUNCTION__, __LINE__);
if (spawn && client->GetPlayer()->WasSentSpawn(spawn->GetID()) && !client->GetPlayer()->WasSpawnRemoved(spawn) && (client->GetPlayer()->CheckQuestRemoveFlag(spawn) || client->GetPlayer()->CheckQuestFlag(spawn) != 0 || (spawn->GetQuestsRequired()->size() > 0 && client->GetPlayer()->CheckQuestRequired(spawn))))
if (spawn && client->GetPlayer()->WasSentSpawn(spawn->GetID()) && !client->GetPlayer()->WasSpawnRemoved(spawn) && (client->GetPlayer()->CheckQuestRemoveFlag(spawn) || client->GetPlayer()->CheckQuestFlag(spawn) != 0 || (spawn->HasQuestsRequired() && client->GetPlayer()->CheckQuestRequired(spawn))))
SendSpawnChanges(spawn, client, false, true);
spawn->m_requiredQuests.releasereadlock(__FUNCTION__, __LINE__);
}