Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Generals/Code/GameEngine/Include/GameLogic/GameLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ class GameLogic : public SubsystemInterface, public Snapshot

/// factory for TheTerrainLogic, called from init()
virtual TerrainLogic *createTerrainLogic();
virtual GhostObjectManager *createGhostObjectManager();
virtual GhostObjectManager *createGhostObjectManager(bool headless = false);

GameMode m_gameMode;
Int m_rankLevelLimit;
Expand Down
14 changes: 14 additions & 0 deletions Generals/Code/GameEngine/Include/GameLogic/GhostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,19 @@ inline Bool GhostObjectManager::trackAllPlayers() const
#endif
}

// TheSuperHackers @feature bobtista 19/01/2026
// GhostObjectManager that does nothing for headless mode.
// Note: Does NOT override crc/xfer/loadPostProcess to maintain save compatibility.
class GhostObjectManagerDummy : public GhostObjectManager
{
public:
virtual void reset() override {}
virtual GhostObject *addGhostObject(Object *object, PartitionData *pd) override { return nullptr; }
virtual void removeGhostObject(GhostObject *mod) override {}
virtual void updateOrphanedObjects(int *playerIndexList, int playerIndexCount) override {}
virtual void releasePartitionData() override {}
virtual void restorePartitionData() override {}
};

// the singleton
extern GhostObjectManager *TheGhostObjectManager;
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ void GameLogic::init()
// Create system for holding deleted objects that are
// still in the partition manager because player has a fogged
// view of them.
TheGhostObjectManager = createGhostObjectManager();
TheGhostObjectManager = createGhostObjectManager(TheGlobalData->m_headless);

// create the terrain logic
TheTerrainLogic = createTerrainLogic();
Expand Down Expand Up @@ -3933,7 +3933,7 @@ UnsignedInt GameLogic::getObjectCount()

// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
GhostObjectManager *GameLogic::createGhostObjectManager()
GhostObjectManager *GameLogic::createGhostObjectManager(bool)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dummy

{
return NEW GhostObjectManager;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also return the dummy variant?

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class W3DGameLogic : public GameLogic

/// factory for TheTerrainLogic, called from init()
virtual TerrainLogic *createTerrainLogic() { return NEW W3DTerrainLogic; };
virtual GhostObjectManager *createGhostObjectManager() { return NEW W3DGhostObjectManager; }
// TheSuperHackers @feature bobtista 19/01/2026 Use dummy for headless mode
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superfluous comment

virtual GhostObjectManager *createGhostObjectManager(bool headless) { return headless ? static_cast<GhostObjectManager*>(NEW GhostObjectManagerDummy) : NEW W3DGhostObjectManager; }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better name this dummy, because headless makes assumptions about the use case.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder, why is a cast necessary for the first pointer but not the second?


};
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void W3DRenderObjectSnapshot::update(RenderObjClass *robj, DrawableInfo *drawInf
// ------------------------------------------------------------------------------------------------
Bool W3DRenderObjectSnapshot::addToScene()
{
if (W3DDisplay::m_3DScene != nullptr && !m_robj->Is_In_Scene())
if (!m_robj->Is_In_Scene())
{
W3DDisplay::m_3DScene->Add_Render_Object(m_robj);
return true;
Expand Down
2 changes: 1 addition & 1 deletion GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ class GameLogic : public SubsystemInterface, public Snapshot

/// factory for TheTerrainLogic, called from init()
virtual TerrainLogic *createTerrainLogic();
virtual GhostObjectManager *createGhostObjectManager();
virtual GhostObjectManager *createGhostObjectManager(bool headless = false);

GameMode m_gameMode;
Int m_rankLevelLimit;
Expand Down
14 changes: 14 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/GhostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,19 @@ inline Bool GhostObjectManager::trackAllPlayers() const
#endif
}

// TheSuperHackers @feature bobtista 19/01/2026
// GhostObjectManager that does nothing for headless mode.
// Note: Does NOT override crc/xfer/loadPostProcess to maintain save compatibility.
class GhostObjectManagerDummy : public GhostObjectManager
{
public:
virtual void reset() override {}
virtual GhostObject *addGhostObject(Object *object, PartitionData *pd) override { return nullptr; }
virtual void removeGhostObject(GhostObject *mod) override {}
virtual void updateOrphanedObjects(int *playerIndexList, int playerIndexCount) override {}
virtual void releasePartitionData() override {}
virtual void restorePartitionData() override {}
};

// the singleton
extern GhostObjectManager *TheGhostObjectManager;
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ void GameLogic::init()
// Create system for holding deleted objects that are
// still in the partition manager because player has a fogged
// view of them.
TheGhostObjectManager = createGhostObjectManager();
TheGhostObjectManager = createGhostObjectManager(TheGlobalData->m_headless);

// create the terrain logic
TheTerrainLogic = createTerrainLogic();
Expand Down Expand Up @@ -4492,7 +4492,7 @@ UnsignedInt GameLogic::getObjectCount()

// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
GhostObjectManager *GameLogic::createGhostObjectManager()
GhostObjectManager *GameLogic::createGhostObjectManager(bool)
{
return NEW GhostObjectManager;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class W3DGameLogic : public GameLogic

/// factory for TheTerrainLogic, called from init()
virtual TerrainLogic *createTerrainLogic() { return NEW W3DTerrainLogic; };
virtual GhostObjectManager *createGhostObjectManager() { return NEW W3DGhostObjectManager; }
// TheSuperHackers @feature bobtista 19/01/2026 Use dummy for headless mode
virtual GhostObjectManager *createGhostObjectManager(bool headless) { return headless ? static_cast<GhostObjectManager*>(NEW GhostObjectManagerDummy) : NEW W3DGhostObjectManager; }

};
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void W3DRenderObjectSnapshot::update(RenderObjClass *robj, DrawableInfo *drawInf
// ------------------------------------------------------------------------------------------------
Bool W3DRenderObjectSnapshot::addToScene()
{
if (W3DDisplay::m_3DScene != nullptr && !m_robj->Is_In_Scene())
if (!m_robj->Is_In_Scene())
{
W3DDisplay::m_3DScene->Add_Render_Object(m_robj);
return true;
Expand Down
Loading