Skip to content

Commit daf86de

Browse files
authored
fix(object): Save and load game object list in correct order (TheSuperHackers#2161)
1 parent b1c456b commit daf86de

4 files changed

Lines changed: 62 additions & 3 deletions

File tree

Generals/Code/GameEngine/Include/GameLogic/Object.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ class Object : public Thing, public Snapshot
166166

167167
Object* getNextObject() { return m_next; }
168168
const Object* getNextObject() const { return m_next; }
169+
Object* getPrevObject() { return m_prev; }
170+
const Object* getPrevObject() const { return m_prev; }
171+
void friend_setNextObject(Object* obj) { m_next = obj; }
172+
void friend_setPrevObject(Object* obj) { m_prev = obj; }
169173

170174
void updateObjValuesFromMapProperties(Dict* properties); ///< Brings in properties set in the editor.
171175

Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4244,13 +4244,14 @@ void GameLogic::prepareLogicForObjectLoad()
42444244
* this version breaks compatibility with previous versions. (CBD)
42454245
* 5: Added xfering the BuildAssistant's sell list.
42464246
* 9: Added m_rankPointsToAddAtGameStart, or else on a load game, your RestartGame button will forget your exp
4247+
* 10: TheSuperHackers @tweak Save objects in reverse order so they load in correct order. Reverse object list for old saves.
42474248
*/
42484249
// ------------------------------------------------------------------------------------------------
42494250
void GameLogic::xfer( Xfer *xfer )
42504251
{
42514252

42524253
// version
4253-
const XferVersion currentVersion = 9;
4254+
const XferVersion currentVersion = 10;
42544255
XferVersion version = currentVersion;
42554256
xfer->xferVersion( &version, currentVersion );
42564257

@@ -4284,7 +4285,13 @@ void GameLogic::xfer( Xfer *xfer )
42844285
if( xfer->getXferMode() == XFER_SAVE )
42854286
{
42864287

4288+
// TheSuperHackers @fix bobtista 27/01/2026 Save objects in reverse order (newest first)
4289+
// so they load in the correct order (oldest objects at head of list).
4290+
Object *lastObj = nullptr;
42874291
for( obj = getFirstObject(); obj; obj = obj->getNextObject() )
4292+
lastObj = obj;
4293+
4294+
for( obj = lastObj; obj; obj = obj->getPrevObject() )
42884295
{
42894296

42904297
// get the object TOC entry for this template
@@ -4367,6 +4374,25 @@ void GameLogic::xfer( Xfer *xfer )
43674374

43684375
}
43694376

4377+
// TheSuperHackers @fix bobtista 27/01/2026 Reverse object list for old saves.
4378+
// Old saves stored objects oldest-first, which results in reversed order when loaded
4379+
// since objects are prepended during creation. Version 10+ saves in reverse order.
4380+
if ( version <= 9 )
4381+
{
4382+
Object *prev = nullptr;
4383+
Object *current = m_objList;
4384+
Object *next = nullptr;
4385+
while ( current != nullptr )
4386+
{
4387+
next = current->getNextObject();
4388+
current->friend_setNextObject( prev );
4389+
current->friend_setPrevObject( next );
4390+
prev = current;
4391+
current = next;
4392+
}
4393+
m_objList = prev;
4394+
}
4395+
43704396
}
43714397

43724398
// campaign info

GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ class Object : public Thing, public Snapshot
172172

173173
Object* getNextObject() { return m_next; }
174174
const Object* getNextObject() const { return m_next; }
175+
Object* getPrevObject() { return m_prev; }
176+
const Object* getPrevObject() const { return m_prev; }
177+
void friend_setNextObject(Object* obj) { m_next = obj; }
178+
void friend_setPrevObject(Object* obj) { m_prev = obj; }
175179

176180
void updateObjValuesFromMapProperties(Dict* properties); ///< Brings in properties set in the editor.
177181

GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4804,13 +4804,14 @@ void GameLogic::prepareLogicForObjectLoad()
48044804
* 5: Added xfering the BuildAssistant's sell list.
48054805
* 9: Added m_rankPointsToAddAtGameStart, or else on a load game, your RestartGame button will forget your exp
48064806
* 10: xfer m_superweaponRestriction
4807+
* 11: TheSuperHackers @tweak Save objects in reverse order so they load in correct order
48074808
*/
48084809
// ------------------------------------------------------------------------------------------------
48094810
void GameLogic::xfer( Xfer *xfer )
48104811
{
48114812

48124813
// version
4813-
const XferVersion currentVersion = 10;
4814+
const XferVersion currentVersion = 11;
48144815
XferVersion version = currentVersion;
48154816
xfer->xferVersion( &version, currentVersion );
48164817

@@ -4843,8 +4844,13 @@ void GameLogic::xfer( Xfer *xfer )
48434844
ObjectTOCEntry *tocEntry;
48444845
if( xfer->getXferMode() == XFER_SAVE )
48454846
{
4846-
4847+
// TheSuperHackers @fix bobtista 27/01/2026 Save objects in reverse order (newest first)
4848+
// so they load in the correct order (oldest objects at head of list).
4849+
Object *lastObj = nullptr;
48474850
for( obj = getFirstObject(); obj; obj = obj->getNextObject() )
4851+
lastObj = obj;
4852+
4853+
for( obj = lastObj; obj; obj = obj->getPrevObject() )
48484854
{
48494855

48504856
// get the object TOC entry for this template
@@ -4927,6 +4933,25 @@ void GameLogic::xfer( Xfer *xfer )
49274933

49284934
}
49294935

4936+
// TheSuperHackers @fix bobtista 27/01/2026 Reverse object list for old saves.
4937+
// Old saves stored objects oldest-first, which results in reversed order when loaded
4938+
// since objects are prepended during creation. Version 11+ saves in reverse order.
4939+
if ( version <= 10 )
4940+
{
4941+
Object *prev = nullptr;
4942+
Object *current = m_objList;
4943+
Object *next = nullptr;
4944+
while ( current != nullptr )
4945+
{
4946+
next = current->getNextObject();
4947+
current->friend_setNextObject( prev );
4948+
current->friend_setPrevObject( next );
4949+
prev = current;
4950+
current = next;
4951+
}
4952+
m_objList = prev;
4953+
}
4954+
49304955
}
49314956

49324957
// campaign info

0 commit comments

Comments
 (0)