From 7db34100e16219e505188ddef8e600da7945420a Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 2 Feb 2026 16:41:52 -0600 Subject: [PATCH 1/5] feature(headless): Add ViewDummy for headless mode --- Core/GameEngine/Include/GameClient/View.h | 22 +++++++++++++++++++ .../GameEngine/Source/GameClient/InGameUI.cpp | 6 ++--- .../W3DDevice/GameClient/W3DInGameUI.h | 4 +++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Core/GameEngine/Include/GameClient/View.h b/Core/GameEngine/Include/GameClient/View.h index 16d7171755b..cacbed83d4b 100644 --- a/Core/GameEngine/Include/GameClient/View.h +++ b/Core/GameEngine/Include/GameClient/View.h @@ -331,5 +331,27 @@ class ViewLocation } }; +// TheSuperHackers @feature bobtista 31/01/2026 +// View that does nothing. Used for Headless Mode. +class ViewDummy : public View +{ +public: + virtual Drawable *pickDrawable( const ICoord2D *screen, Bool forceAttack, PickType pickType ) { return nullptr; } + virtual Int iterateDrawablesInRegion( IRegion2D *screenRegion, Bool (*callback)( Drawable *draw, void *userData ), void *userData ) { return 0; } + virtual void forceRedraw() {} + virtual const Coord3D& get3DCameraPosition() const { static Coord3D zero = {0,0,0}; return zero; } + virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) { return WTS_INVALID; } + virtual void screenToWorld( const ICoord2D *s, Coord3D *w ) {} + virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) {} + virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) {} + virtual void drawView( void ) {} + virtual void updateView(void) {} + virtual void stepView() {} + virtual void setGuardBandBias( const Coord2D *gb ) {} + +protected: + virtual void xfer( Xfer *xfer ) {} +}; + // EXTERNALS ////////////////////////////////////////////////////////////////////////////////////// extern View *TheTacticalView; ///< the main tactical interface to the game world diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index 3b852e3f676..d031448ba3f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -1367,17 +1367,17 @@ void InGameUI::init() been moved to where all the other translators are attached in game client */ // create the tactical view - if (TheDisplay) + TheTacticalView = createView(); + if (TheTacticalView && TheDisplay) { - TheTacticalView = createView(); TheTacticalView->init(); TheDisplay->attachView( TheTacticalView ); // make the tactical display the full screen width and height TheTacticalView->setWidth( TheDisplay->getWidth() ); TheTacticalView->setHeight( TheDisplay->getHeight() ); + TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); } - TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); /** @todo this may be the wrong place to create the sidebar, but for now this is where it lives */ diff --git a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index f239e05e1f9..e69b349975a 100644 --- a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -36,6 +36,7 @@ // SYSTEM INCLUDES //////////////////////////////////////////////////////////// // USER INCLUDES ////////////////////////////////////////////////////////////// +#include "Common/GlobalData.h" #include "GameClient/InGameUI.h" #include "GameClient/View.h" #include "W3DDevice/GameClient/W3DView.h" @@ -69,7 +70,8 @@ class W3DInGameUI : public InGameUI protected: /// factory for views - virtual View *createView() { return NEW W3DView; } + // TheSuperHackers @fix bobtista 31/01/2026 Return dummy in headless mode + virtual View *createView() { return TheGlobalData->m_headless ? NEW ViewDummy : NEW W3DView; } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback From 8509cf8e9b5c86ba1e149d6a4bac94fdab5fe1e0 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Mon, 2 Feb 2026 16:42:31 -0600 Subject: [PATCH 2/5] feature(headless): Replicate ViewDummy to Generals --- Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp | 6 +++--- .../Include/W3DDevice/GameClient/W3DInGameUI.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp index a7c70a70f7b..87e66bad696 100644 --- a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -1337,17 +1337,17 @@ void InGameUI::init() been moved to where all the other translators are attached in game client */ // create the tactical view - if (TheDisplay) + TheTacticalView = createView(); + if (TheTacticalView && TheDisplay) { - TheTacticalView = createView(); TheTacticalView->init(); TheDisplay->attachView( TheTacticalView ); // make the tactical display the full screen width and height TheTacticalView->setWidth( TheDisplay->getWidth() ); TheTacticalView->setHeight( TheDisplay->getHeight() ); + TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); } - TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); /** @todo this may be the wrong place to create the sidebar, but for now this is where it lives */ diff --git a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index 02109bc27cd..f2e54e3b231 100644 --- a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -36,6 +36,7 @@ // SYSTEM INCLUDES //////////////////////////////////////////////////////////// // USER INCLUDES ////////////////////////////////////////////////////////////// +#include "Common/GlobalData.h" #include "GameClient/InGameUI.h" #include "GameClient/View.h" #include "W3DDevice/GameClient/W3DView.h" @@ -69,7 +70,8 @@ class W3DInGameUI : public InGameUI protected: /// factory for views - virtual View *createView() { return NEW W3DView; } + // TheSuperHackers @fix bobtista 31/01/2026 Return dummy in headless mode + virtual View *createView() { return TheGlobalData->m_headless ? NEW ViewDummy : NEW W3DView; } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback From ed1c2fb6ae33eb3566b02d40302c20a41eef8710 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 3 Feb 2026 13:06:12 -0600 Subject: [PATCH 3/5] bugfix(headless): Fix ViewDummy xfer save corruption and VC6 ternary build error --- Core/GameEngine/Include/GameClient/View.h | 4 ++-- .../Include/W3DDevice/GameClient/W3DInGameUI.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/GameEngine/Include/GameClient/View.h b/Core/GameEngine/Include/GameClient/View.h index cacbed83d4b..3a5daed192f 100644 --- a/Core/GameEngine/Include/GameClient/View.h +++ b/Core/GameEngine/Include/GameClient/View.h @@ -349,8 +349,8 @@ class ViewDummy : public View virtual void stepView() {} virtual void setGuardBandBias( const Coord2D *gb ) {} -protected: - virtual void xfer( Xfer *xfer ) {} + // TheSuperHackers @bugfix bobtista 03/02/2026 Do not override View::xfer(). The base + // implementation must run to serialize valid view state for save file compatibility. }; // EXTERNALS ////////////////////////////////////////////////////////////////////////////////////// diff --git a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index e69b349975a..7998c19319a 100644 --- a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -71,7 +71,7 @@ class W3DInGameUI : public InGameUI /// factory for views // TheSuperHackers @fix bobtista 31/01/2026 Return dummy in headless mode - virtual View *createView() { return TheGlobalData->m_headless ? NEW ViewDummy : NEW W3DView; } + virtual View *createView() { return TheGlobalData->m_headless ? static_cast(NEW ViewDummy) : NEW W3DView; } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback From a9f47a3db98734fd06b5320d3652bd84a3f2ab76 Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 3 Feb 2026 13:06:16 -0600 Subject: [PATCH 4/5] bugfix(headless): Replicate VC6 ternary build fix to Generals --- .../GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index f2e54e3b231..5ee0562d738 100644 --- a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -71,7 +71,7 @@ class W3DInGameUI : public InGameUI /// factory for views // TheSuperHackers @fix bobtista 31/01/2026 Return dummy in headless mode - virtual View *createView() { return TheGlobalData->m_headless ? NEW ViewDummy : NEW W3DView; } + virtual View *createView() { return TheGlobalData->m_headless ? static_cast(NEW ViewDummy) : NEW W3DView; } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback From e439eee5c8a282472cbd3c8d82994025d491227d Mon Sep 17 00:00:00 2001 From: Bobby Battista Date: Tue, 24 Feb 2026 09:56:25 -0500 Subject: [PATCH 5/5] style: Expand inline function bodies to multi-line for breakpoint-friendly formatting --- Core/GameEngine/Include/GameClient/View.h | 53 ++++++++++++++----- .../W3DDevice/GameClient/W3DInGameUI.h | 5 +- .../W3DDevice/GameClient/W3DInGameUI.h | 5 +- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/Core/GameEngine/Include/GameClient/View.h b/Core/GameEngine/Include/GameClient/View.h index 3a5daed192f..8d1e9ebac55 100644 --- a/Core/GameEngine/Include/GameClient/View.h +++ b/Core/GameEngine/Include/GameClient/View.h @@ -336,18 +336,47 @@ class ViewLocation class ViewDummy : public View { public: - virtual Drawable *pickDrawable( const ICoord2D *screen, Bool forceAttack, PickType pickType ) { return nullptr; } - virtual Int iterateDrawablesInRegion( IRegion2D *screenRegion, Bool (*callback)( Drawable *draw, void *userData ), void *userData ) { return 0; } - virtual void forceRedraw() {} - virtual const Coord3D& get3DCameraPosition() const { static Coord3D zero = {0,0,0}; return zero; } - virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) { return WTS_INVALID; } - virtual void screenToWorld( const ICoord2D *s, Coord3D *w ) {} - virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) {} - virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) {} - virtual void drawView( void ) {} - virtual void updateView(void) {} - virtual void stepView() {} - virtual void setGuardBandBias( const Coord2D *gb ) {} + virtual Drawable *pickDrawable( const ICoord2D *screen, Bool forceAttack, PickType pickType ) + { + return nullptr; + } + virtual Int iterateDrawablesInRegion( IRegion2D *screenRegion, Bool (*callback)( Drawable *draw, void *userData ), void *userData ) + { + return 0; + } + virtual void forceRedraw() + { + } + virtual const Coord3D& get3DCameraPosition() const + { + static Coord3D zero = {0,0,0}; + return zero; + } + virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) + { + return WTS_INVALID; + } + virtual void screenToWorld( const ICoord2D *s, Coord3D *w ) + { + } + virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) + { + } + virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) + { + } + virtual void drawView( void ) + { + } + virtual void updateView(void) + { + } + virtual void stepView() + { + } + virtual void setGuardBandBias( const Coord2D *gb ) + { + } // TheSuperHackers @bugfix bobtista 03/02/2026 Do not override View::xfer(). The base // implementation must run to serialize valid view state for save file compatibility. diff --git a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index 5ee0562d738..e60bdb5dc06 100644 --- a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -71,7 +71,10 @@ class W3DInGameUI : public InGameUI /// factory for views // TheSuperHackers @fix bobtista 31/01/2026 Return dummy in headless mode - virtual View *createView() { return TheGlobalData->m_headless ? static_cast(NEW ViewDummy) : NEW W3DView; } + virtual View *createView() + { + return TheGlobalData->m_headless ? static_cast(NEW ViewDummy) : NEW W3DView; + } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback diff --git a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index 7998c19319a..03886aa6e9f 100644 --- a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -71,7 +71,10 @@ class W3DInGameUI : public InGameUI /// factory for views // TheSuperHackers @fix bobtista 31/01/2026 Return dummy in headless mode - virtual View *createView() { return TheGlobalData->m_headless ? static_cast(NEW ViewDummy) : NEW W3DView; } + virtual View *createView() + { + return TheGlobalData->m_headless ? static_cast(NEW ViewDummy) : NEW W3DView; + } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback