From 43fade82e532817681a1455f19a91f321ce1134f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 Feb 2021 01:03:38 -0500 Subject: [PATCH] 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. --- zone/entity.cpp | 3 +++ zone/lua_parser.cpp | 10 ++++++++++ zone/lua_parser.h | 1 + zone/quest_interface.h | 1 + zone/quest_parser_collection.cpp | 8 ++++++++ zone/quest_parser_collection.h | 1 + 6 files changed, 24 insertions(+) diff --git a/zone/entity.cpp b/zone/entity.cpp index f79409249..4bf59ddf0 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -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); diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 494e3e0e2..59b10d4bf 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -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()) { diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 8265a191f..d058daf13 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -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, diff --git a/zone/quest_interface.h b/zone/quest_interface.h index a2a6c73c8..d0f121cb6 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -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 &err) { diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index a4d9a5e21..625425839 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -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); } diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index a5dc07a95..082b5b6f4 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -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);