From 42a3ca3d560084a60b2f18828b25d32b87a6913a Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 9 Jul 2025 20:34:29 -0400 Subject: [PATCH] Move OnLoad to after everything is done serializing Makes behavior much more consistent and safer. --- src/g_level.cpp | 4 ++++ src/playsim/dthinker.cpp | 52 ++++++++++++++++++++++++++++++---------- src/playsim/dthinker.h | 3 ++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index f5921948e..9ea40c929 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1538,6 +1538,10 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au { I_Error("no start for player %d found.", pnumerr); } + + // If loading in from existing data, allow things to reinitialize if needed. + if (FromSnapshot || savegamerestore) + Thinkers.OnLoad(); } diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index 2d37ffcfd..a5cffd67a 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -362,6 +362,20 @@ void FThinkerCollection::DestroyAllThinkers(bool fullgc) // //========================================================================== +void FThinkerCollection::OnLoad() +{ + for (auto& list : FreshThinkers) + list.OnLoad(); + for (auto& list : Thinkers) + list.OnLoad(); +} + +//========================================================================== +// +// +// +//========================================================================== + void FThinkerCollection::SerializeThinkers(FSerializer &arc, bool hubLoad) { //DThinker *thinker; @@ -415,12 +429,12 @@ void FThinkerCollection::SerializeThinkers(FSerializer &arc, bool hubLoad) else if (thinker->ObjectFlags & OF_JustSpawned) { FreshThinkers[i].AddTail(thinker); - thinker->CallPostSerialize(); + thinker->PostSerialize(); } else { Thinkers[i].AddTail(thinker); - thinker->CallPostSerialize(); + thinker->PostSerialize(); } } } @@ -645,6 +659,30 @@ void FThinkerList::SaveList(FSerializer &arc) // //========================================================================== +void FThinkerList::OnLoad() +{ + DThinker* node = GetHead(); + if (node == nullptr) + return; + + while (node != Sentinel) + { + NextToThink = node->NextThinker; + if (!(node->ObjectFlags & OF_EuthanizeMe)) + { + IFOVERRIDENVIRTUALPTRNAME(node, NAME_Thinker, OnLoad) + VMCallVoid(func, node); + } + node = NextToThink; + } +} + +//========================================================================== +// +// +// +//========================================================================== + int FThinkerList::TickThinkers(FThinkerList *dest) { int count = 0; @@ -833,16 +871,6 @@ void DThinker::PostSerialize() { } -void DThinker::CallPostSerialize() -{ - PostSerialize(); - IFOVERRIDENVIRTUALPTRNAME(this, NAME_Thinker, OnLoad) - { - VMValue params[] = { this }; - VMCall(func, params, 1, nullptr, 0); - } -} - //========================================================================== // // diff --git a/src/playsim/dthinker.h b/src/playsim/dthinker.h index 95c2bb4bc..8a446e461 100644 --- a/src/playsim/dthinker.h +++ b/src/playsim/dthinker.h @@ -60,6 +60,7 @@ struct FThinkerList bool IsEmpty() const; void DestroyThinkers(); bool DoDestroyThinkers(); + void OnLoad(); int TickThinkers(FThinkerList *dest); // Returns: # of thinkers ticked int ProfileThinkers(FThinkerList *dest); void SaveList(FSerializer &arc); @@ -83,6 +84,7 @@ struct FThinkerCollection void DestroyAllThinkers(bool fullgc = true); void SerializeThinkers(FSerializer &arc, bool keepPlayers); void MarkRoots(); + void OnLoad(); DThinker *FirstThinker(int statnum); void Link(DThinker *thinker, int statnum); @@ -105,7 +107,6 @@ public: virtual void PostBeginPlay (); // Called just before the first tick virtual void CallPostBeginPlay(); // different in actor. virtual void PostSerialize(); - void CallPostSerialize(); void Serialize(FSerializer &arc) override; size_t PropagateMark();