Fix ReloadQuest on Shutdown crash related to encounters

Basically, EntityList::RemoveAllEncounters is called before ReloadQuests
resulting in stale pointers in the lua_encounters map.

We just have to remove the entry from the map.
This commit is contained in:
Michael Cook (mackal) 2021-02-24 01:03:38 -05:00
parent 66d24ff419
commit 43fade82e5
6 changed files with 24 additions and 0 deletions

View File

@ -602,6 +602,8 @@ void EntityList::EncounterProcess()
auto it = encounter_list.begin();
while (it != encounter_list.end()) {
if (!it->second->Process()) {
// if Process is returning false here, we probably just got called from ReloadQuests .. oh well
parse->RemoveEncounter(it->second->GetName());
safe_delete(it->second);
free_ids.push(it->first);
it = encounter_list.erase(it);
@ -2565,6 +2567,7 @@ void EntityList::RemoveAllEncounters()
{
auto it = encounter_list.begin();
while (it != encounter_list.end()) {
parse->RemoveEncounter(it->second->GetName());
safe_delete(it->second);
free_ids.push(it->first);
it = encounter_list.erase(it);

View File

@ -988,6 +988,16 @@ void LuaParser::ReloadQuests() {
}
}
/*
* This function is intended only to clean up lua_encounters when the Encounter object is
* about to be destroyed. It won't clean up memory else where, since the caller of this
* function is responsible for that
*/
void LuaParser::RemoveEncounter(const std::string &name)
{
lua_encounters.erase(name);
}
void LuaParser::LoadScript(std::string filename, std::string package_name) {
auto iter = loaded_.find(package_name);
if(iter != loaded_.end()) {

View File

@ -71,6 +71,7 @@ public:
virtual std::string GetVar(std::string name);
virtual void Init();
virtual void ReloadQuests();
virtual void RemoveEncounter(const std::string &name);
virtual uint32 GetIdentifier() { return 0xb0712acc; }
virtual int DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,

View File

@ -78,6 +78,7 @@ public:
virtual void Init() { }
virtual void ReloadQuests() { }
virtual uint32 GetIdentifier() = 0;
virtual void RemoveEncounter(const std::string &name) { }
//TODO: Set maximum quest errors instead of hard coding it
virtual void GetErrors(std::list<std::string> &err) {

View File

@ -89,6 +89,14 @@ void QuestParserCollection::ReloadQuests(bool reset_timers) {
}
}
void QuestParserCollection::RemoveEncounter(const std::string name) {
auto iter = _load_precedence.begin();
while(iter != _load_precedence.end()) {
(*iter)->RemoveEncounter(name);
++iter;
}
}
bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt) {
return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt);
}

View File

@ -65,6 +65,7 @@ public:
void AddVar(std::string name, std::string val);
void Init();
void ReloadQuests(bool reset_timers = true);
void RemoveEncounter(const std::string name);
bool HasQuestSub(uint32 npcid, QuestEventID evt);
bool PlayerHasQuestSub(QuestEventID evt);