From 60472c2b45a10e972292fe0328354e45de0f43ac Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 22 Feb 2008 01:45:32 +0000 Subject: [PATCH] - Fixed: DThinker::SerializeAll() did not serialize any thinkers in the FreshThinkers lists. These thinkers would still be saved in the savegame if there were other references to them, but they would not go in any thinker lists when loading the savegame. An easy way to exercise this bug is to give yourself something new with the console and then save the game right away without closing the console by using the "save" command. The item would be stored in the savegame thanks to its presence in the Inventory list, but it wouldn't be in a thinker list when the game was reloaded because it was still in the FreshThinkers list when the game was saved. SVN r763 (trunk) --- docs/rh-log.txt | 9 +++++++ src/dthinker.cpp | 51 ++++++++++++++++++++++++-------------- src/dthinker.h | 2 +- src/g_shared/a_pickups.cpp | 4 +-- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5adc22e0fb..b0ec5eab99 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,13 @@ February 21, 2008 +- Fixed: DThinker::SerializeAll() did not serialize any thinkers in the + FreshThinkers lists. These thinkers would still be saved in the savegame if + there were other references to them, but they would not go in any thinker + lists when loading the savegame. An easy way to exercise this bug is to + give yourself something new with the console and then save the game right + away without closing the console by using the "save" command. The item + would be stored in the savegame thanks to its presence in the Inventory + list, but it wouldn't be in a thinker list when the game was reloaded + because it was still in the FreshThinkers list when the game was saved. - Fixed: PO_Busy() did not check for a NULL return from GetPolyobj(). - Fixed two problems with printfs from the net controller stuff: one of them is totally valid, and the other is GCC not being as nice as VC++. diff --git a/src/dthinker.cpp b/src/dthinker.cpp index e1e6896a0f..fa6bfe0596 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -52,9 +52,21 @@ List DThinker::Thinkers[MAX_STATNUM+1]; List DThinker::FreshThinkers[MAX_STATNUM+1]; bool DThinker::bSerialOverride = false; -void DThinker::SerializeAll (FArchive &arc, bool hubLoad) +void DThinker::SaveList(FArchive &arc, Node *node) +{ + if (node->Succ != NULL) + { + do + { + DThinker *thinker = static_cast(node); + arc << thinker; + node = node->Succ; + } while (node->Succ != NULL); + } +} + +void DThinker::SerializeAll(FArchive &arc, bool hubLoad) { - Node *node; DThinker *thinker; BYTE stat; int statcount; @@ -67,29 +79,21 @@ void DThinker::SerializeAll (FArchive &arc, bool hubLoad) // the thinker lists here instead of relying on the archiver to do it // for us. - if (arc.IsStoring ()) + if (arc.IsStoring()) { for (statcount = i = 0; i <= MAX_STATNUM; i++) { - if (!Thinkers[i].IsEmpty ()) - { - statcount++; - } + statcount += (!Thinkers[i].IsEmpty() || !FreshThinkers[i].IsEmpty()); } arc << statcount; for (i = 0; i <= MAX_STATNUM; i++) { - node = Thinkers[i].Head; - if (node->Succ != NULL) + if (!Thinkers[i].IsEmpty() || !FreshThinkers[i].IsEmpty()) { stat = i; arc << stat; - do - { - thinker = static_cast (node); - arc << thinker; - node = node->Succ; - } while (node->Succ != NULL); + SaveList(arc, Thinkers[i].Head); + SaveList(arc, FreshThinkers[i].Head); thinker = NULL; arc << thinker; // Save a final NULL for this list } @@ -98,9 +102,9 @@ void DThinker::SerializeAll (FArchive &arc, bool hubLoad) else { if (hubLoad) - DestroyMostThinkers (); + DestroyMostThinkers(); else - DestroyAllThinkers (); + DestroyAllThinkers(); // Prevent the constructor from inserting thinkers into a list. bSerialOverride = true; @@ -113,7 +117,16 @@ void DThinker::SerializeAll (FArchive &arc, bool hubLoad) arc << stat << thinker; while (thinker != NULL) { - Thinkers[stat].AddTail (thinker); + // Thinkers with the OF_JustSpawned flag set go in the FreshThinkers + // list. Anything else goes in the regular Thinkers list. + if (thinker->ObjectFlags & OF_JustSpawned) + { + FreshThinkers[stat].AddTail(thinker); + } + else + { + Thinkers[stat].AddTail(thinker); + } arc << thinker; } statcount--; @@ -122,7 +135,7 @@ void DThinker::SerializeAll (FArchive &arc, bool hubLoad) catch (class CDoomError &) { bSerialOverride = false; - DestroyAllThinkers (); + DestroyAllThinkers(); throw; } bSerialOverride = false; diff --git a/src/dthinker.h b/src/dthinker.h index ae8989adc6..f7905c5b8d 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -74,7 +74,7 @@ private: static void DestroyThinkersInList (Node *first); static void DestroyMostThinkersInList (List &list, int stat); static int TickThinkers (List *list, List *dest); // Returns: # of thinkers ticked - + static void SaveList(FArchive &arc, Node *node); static List Thinkers[MAX_STATNUM+1]; // Current thinkers static List FreshThinkers[MAX_STATNUM+1]; // Newly created thinkers diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 9618c0950b..a7660bdfb8 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1257,9 +1257,9 @@ CCMD (printinv) } for (item = players[pnum].mo->Inventory; item != NULL; item = item->Inventory) { - Printf ("%s #%u (%d/%d) <%p/%p>\n", item->GetClass()->TypeName.GetChars(), + Printf ("%s #%u (%d/%d)\n", item->GetClass()->TypeName.GetChars(), item->InventoryID, - item->Amount, item->MaxAmount, static_cast(item)->Pred, item->Succ); + item->Amount, item->MaxAmount); } }