Skip to content

feature(headless): Add GhostObjectManagerDummy for headless mode#2244

Open
bobtista wants to merge 4 commits intoTheSuperHackers:mainfrom
bobtista:bobtista/ghost-object-manager-dummy
Open

feature(headless): Add GhostObjectManagerDummy for headless mode#2244
bobtista wants to merge 4 commits intoTheSuperHackers:mainfrom
bobtista:bobtista/ghost-object-manager-dummy

Conversation

@bobtista
Copy link

@bobtista bobtista commented Feb 2, 2026

Summary

  • Adds GhostObjectManagerDummy class that provides no-op implementations for headless mode
  • Factory in W3DGameLogic returns dummy when m_headless is true
  • Intentionally does NOT override crc/xfer/loadPostProcess to maintain save compatibility

Related

Split from #2139 per @xezon's suggestion to review each dummy class separately.

@greptile-apps
Copy link

greptile-apps bot commented Feb 2, 2026

Greptile Overview

Greptile Summary

Adds GhostObjectManagerDummy class for headless mode, providing no-op implementations for ghost object management which handles fog-of-war memory for objects. When running in headless mode, the factory in W3DGameLogic::createGhostObjectManager() now returns the dummy instead of the full W3DGhostObjectManager. This prevents unnecessary rendering operations since ghost objects are purely visual features.

The PR also removes the W3DDisplay::m_3DScene != nullptr check in W3DRenderObjectSnapshot::addToScene() that was previously added in #2133. This check is now redundant because the dummy manager returns nullptr from addGhostObject(), preventing any W3DGhostObject instances from being created in headless mode, which means addToScene() will never be called.

Key design decisions:

  • Intentionally does NOT override crc/xfer/loadPostProcess to maintain save game compatibility
  • Mirrors the same pattern used for other dummy classes in the headless implementation
  • Changes are replicated identically across both Generals/ and GeneralsMD/ directories

Confidence Score: 5/5

  • Safe to merge with no issues found
  • The implementation follows established patterns for headless dummy classes, correctly preserves save compatibility by not overriding serialization methods, and the removal of the null check is logically sound since the dummy prevents ghost object creation entirely
  • No files require special attention

Important Files Changed

Filename Overview
Generals/Code/GameEngine/Include/GameLogic/GhostObject.h Added GhostObjectManagerDummy class with no-op implementations for headless mode
Generals/Code/GameEngineDevice/Include/W3DDevice/GameLogic/W3DGameLogic.h Modified factory to return GhostObjectManagerDummy when m_headless is true
Generals/Code/GameEngineDevice/Source/W3DDevice/GameLogic/W3DGhostObject.cpp Removed m_3DScene null check in addToScene(), now redundant with dummy implementation
GeneralsMD/Code/GameEngine/Include/GameLogic/GhostObject.h Added GhostObjectManagerDummy class with no-op implementations for headless mode
GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameLogic/W3DGameLogic.h Modified factory to return GhostObjectManagerDummy when m_headless is true
GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameLogic/W3DGhostObject.cpp Removed m_3DScene null check in addToScene(), now redundant with dummy implementation

Sequence Diagram

sequenceDiagram
    participant W3DGameLogic
    participant GhostObjectManagerDummy
    participant PartitionManager
    participant W3DGhostObject

    Note over W3DGameLogic: createGhostObjectManager()
    alt headless mode
        W3DGameLogic->>GhostObjectManagerDummy: NEW GhostObjectManagerDummy
        GhostObjectManagerDummy-->>W3DGameLogic: return dummy instance
    else normal mode
        W3DGameLogic->>W3DGhostObject: NEW W3DGhostObjectManager
        W3DGhostObject-->>W3DGameLogic: return real instance
    end

    Note over PartitionManager: Object enters fog
    alt headless mode with dummy
        PartitionManager->>GhostObjectManagerDummy: addGhostObject(object, pd)
        GhostObjectManagerDummy-->>PartitionManager: return nullptr (no-op)
        Note over PartitionManager: No ghost object created<br/>No scene interaction needed
    else normal mode
        PartitionManager->>W3DGhostObject: addGhostObject(object, pd)
        W3DGhostObject->>W3DGhostObject: Create W3DGhostObject
        W3DGhostObject->>W3DGhostObject: addToScene() - adds to m_3DScene
        W3DGhostObject-->>PartitionManager: return ghost object
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

virtual TerrainLogic *createTerrainLogic( void ) { return NEW W3DTerrainLogic; };
virtual GhostObjectManager *createGhostObjectManager(void) { return NEW W3DGhostObjectManager; }
// TheSuperHackers @feature bobtista 19/01/2026 Use dummy for headless mode
virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_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.

Unnecessary static_cast<GhostObjectManager*> since GhostObjectManagerDummy already inherits from GhostObjectManager

Suggested change
virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_headless ? static_cast<GhostObjectManager*>(NEW GhostObjectManagerDummy) : NEW W3DGhostObjectManager; }
virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_headless ? NEW GhostObjectManagerDummy : NEW W3DGhostObjectManager; }
Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngineDevice/Include/W3DDevice/GameLogic/W3DGameLogic.h
Line: 64:64

Comment:
Unnecessary `static_cast<GhostObjectManager*>` since `GhostObjectManagerDummy` already inherits from `GhostObjectManager`

```suggestion
	virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_headless ? NEW GhostObjectManagerDummy : NEW W3DGhostObjectManager; }
```

How can I resolve this? If you propose a fix, please make it concise.

virtual TerrainLogic *createTerrainLogic( void ) { return NEW W3DTerrainLogic; };
virtual GhostObjectManager *createGhostObjectManager(void) { return NEW W3DGhostObjectManager; }
// TheSuperHackers @feature bobtista 19/01/2026 Use dummy for headless mode
virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_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.

Unnecessary static_cast<GhostObjectManager*> since GhostObjectManagerDummy already inherits from GhostObjectManager

Suggested change
virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_headless ? static_cast<GhostObjectManager*>(NEW GhostObjectManagerDummy) : NEW W3DGhostObjectManager; }
virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_headless ? NEW GhostObjectManagerDummy : NEW W3DGhostObjectManager; }
Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameLogic/W3DGameLogic.h
Line: 64:64

Comment:
Unnecessary `static_cast<GhostObjectManager*>` since `GhostObjectManagerDummy` already inherits from `GhostObjectManager`

```suggestion
	virtual GhostObjectManager *createGhostObjectManager(void) { return TheGlobalData->m_headless ? NEW GhostObjectManagerDummy : NEW W3DGhostObjectManager; }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Author

Choose a reason for hiding this comment

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

I think this is required for VC6, it failed to build without it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant