[Bugfix] Prevent final shutdown from persisting incomplete state. (#4849)

* [Bugfix] Prevent final shutdown from persisting incomplete state.

* [Bugfix] Change shutdown parameters to member variable.
This commit is contained in:
zimp-wow 2025-04-09 20:55:56 -05:00 committed by GitHub
parent f9fe4ea2ec
commit dca892e258
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 65 additions and 17 deletions

View File

@ -38,7 +38,11 @@ inline void SetupStateZone()
SetupZone("soldungb");
zone->Process();
// depop the zone controller
entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->Depop();
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
if (controller != nullptr) {
controller->Depop();
}
entity_list.MobProcess(); // process the depop
}
@ -352,8 +356,12 @@ inline void TestSpawns()
npc->Death(npc, npc->GetHP() + 1, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand);
}
bool condition = (int) entity_list.GetNPCList().size() == 0 && (int) entity_list.GetCorpseList().size() == 115;
RunTest("Spawns > All NPC's killed (0 NPCs) (115 Corpses)", true, condition);
bool condition = (int) entity_list.GetNPCList().size() == 0 && (int) entity_list.GetCorpseList().size() == entries;
RunTest(
fmt::format("Spawns > All NPC's killed (0 NPCs) ([{}] Corpses)", entries),
true,
condition
);
std::vector<uint32_t> spawn2_ids = {};
@ -377,11 +385,15 @@ inline void TestSpawns()
zone->Shutdown();
SetupStateZone();
condition = (int) entity_list.GetNPCList().size() == 0 && (int) entity_list.GetCorpseList().size() == 115;
condition = (int) entity_list.GetNPCList().size() == 0 && (int) entity_list.GetCorpseList().size() == entries;
if (!condition) {
PrintEntityCounts();
}
RunTest("Spawns > After restore (0 NPCs) (115 Corpses)", true, condition);
RunTest(
fmt::format("Spawns > After restore (0 NPCs) ([{}] Corpses)", entries),
true,
condition
);
for (auto &e: entity_list.GetCorpseList()) {
auto c = e.second;
@ -405,11 +417,15 @@ inline void TestSpawns()
zone->Process();
condition = (int) entity_list.GetNPCList().size() == 115 && (int) entity_list.GetCorpseList().size() == 115;
condition = (int) entity_list.GetNPCList().size() == entries && (int) entity_list.GetCorpseList().size() == entries;
if (!condition) {
PrintEntityCounts();
}
RunTest("Spawns > After respawn (115 NPCs) (115 Corpses)", true, condition);
RunTest(
fmt::format("Spawns > After respawn ([{}] NPCs) ([{}] Corpses)", entries, entries),
true,
condition
);
for (auto &c: entity_list.GetCorpseList()) {
c.second->DepopNPCCorpse();
@ -417,11 +433,15 @@ inline void TestSpawns()
entity_list.CorpseProcess();
condition = (int) entity_list.GetNPCList().size() == 115 && (int) entity_list.GetCorpseList().size() == 0;
condition = (int) entity_list.GetNPCList().size() == entries && (int) entity_list.GetCorpseList().size() == 0;
if (!condition) {
PrintEntityCounts();
}
RunTest("Spawns > After respawn (115 NPCs) (0 Corpses)", true, condition);
RunTest(
fmt::format("Spawns > After respawn ([{}] NPCs) (0 Corpses)", entries),
true,
condition
);
// lets set NPC's up with a predictable loottable for testing
uint32_t loottable_id = SeedLootTable();
@ -462,20 +482,28 @@ inline void TestSpawns()
npc->Death(npc, npc->GetHP() + 1, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand);
}
condition = (int) entity_list.GetNPCList().size() == 105 && (int) entity_list.GetCorpseList().size() == 10;
condition = (int) entity_list.GetNPCList().size() == (entries - 10) && (int) entity_list.GetCorpseList().size() == 10;
if (!condition) {
PrintEntityCounts();
}
RunTest("Spawns > Kill 10 NPC's before save/restore (105 NPCs) (10 Corpses)", true, condition);
RunTest(
fmt::format("Spawns > Kill 10 NPC's before save/restore ([{}] NPCs) (10 Corpses)", (entries - 10)),
true,
condition
);
zone->Shutdown();
SetupStateZone();
condition = (int) entity_list.GetNPCList().size() == 105 && (int) entity_list.GetCorpseList().size() == 10;
condition = (int) entity_list.GetNPCList().size() == (entries - 10) && (int) entity_list.GetCorpseList().size() == 10;
if (!condition) {
PrintEntityCounts();
}
RunTest("Spawns > After restore (105 NPCs) (10 Corpses)", true, condition);
RunTest(
fmt::format("Spawns > After restore ([{}] NPCs) (10 Corpses)", (entries - 10)),
true,
condition
);
// validate that all corpses and npc's have cloak of flames
bool test_failed = false;
@ -572,6 +600,14 @@ inline void TestSpawns()
false
);
int max_respawn = 0;
const auto& l = RespawnTimesRepository::All(database);
for (const auto& e : l) {
if (e.duration > max_respawn) {
max_respawn = e.duration;
}
}
entity_list.MobProcess();
zone->Process();
@ -587,16 +623,20 @@ inline void TestSpawns()
npc->SetEntityVariable("previously_spawned", "true");
}
Timer::RollForward(302401); // longest respawn time in zone
Timer::RollForward(max_respawn); // longest respawn time in zone
zone->Process();
entity_list.MobProcess(); // processing depops
condition = (int) entity_list.GetNPCList().size() == 115 && (int) entity_list.GetCorpseList().size() == 10;
condition = (int) entity_list.GetNPCList().size() == entries && (int) entity_list.GetCorpseList().size() == 10;
if (!condition) {
PrintEntityCounts();
PrintZoneNpcs();
}
RunTest("Spawns > After respawn, ensure we have expected entity counts (115 NPCs) (10 Corpses)", true, condition);
RunTest(
fmt::format("Spawns > After respawn, ensure we have expected entity counts ([{}] NPCs) (10 Corpses)", entries),
true,
condition
);
entity_list.MobProcess(); // processing depops

View File

@ -678,6 +678,7 @@ int main(int argc, char **argv)
safe_delete(Config);
if (zone != 0) {
zone->SetSaveZoneState(false);
zone->Shutdown(true);
}
//Fix for Linux world server problem.

View File

@ -887,7 +887,7 @@ void Zone::Shutdown(bool quiet)
c.second->WorldKick();
}
if (RuleB(Zone, StateSavingOnShutdown) && zone && zone->IsLoaded()) {
if (m_save_zone_state && RuleB(Zone, StateSavingOnShutdown) && zone && zone->IsLoaded()) {
SaveZoneState();
}
@ -1010,6 +1010,7 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
SetIdleWhenEmpty(true);
SetSecondsBeforeIdle(60);
SetSaveZoneState(false);
if (database.GetServerType() == 1) {
pvpzone = true;
@ -1204,6 +1205,8 @@ bool Zone::Init(bool is_static) {
}
content_db.PopulateZoneSpawnList(zoneid, spawn2_list, GetInstanceVersion());
SetSaveZoneState(true);
database.LoadCharacterCorpses(zoneid, instanceid);
content_db.LoadTraps(short_name, GetInstanceVersion());

View File

@ -353,6 +353,9 @@ public:
uint32 GetInstanceTimeRemaining() const;
void SetInstanceTimeRemaining(uint32 instance_time_remaining);
inline bool GetSaveZoneState() const { return m_save_zone_state; }
inline void SetSaveZoneState(bool save_state) { m_save_zone_state = save_state; }
/**
* GMSay Callback for LogSys
*
@ -516,6 +519,7 @@ private:
uint32 m_last_ucss_update;
bool m_idle_when_empty;
uint32 m_seconds_before_idle;
bool m_save_zone_state;
GlobalLootManager m_global_loot;
LinkedList<ZoneClientAuth_Struct *> client_auth_list;