From ffe9f5e4383a51c06a3b84e4901a5408f55ebf45 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:22:44 +0100 Subject: [PATCH 1/8] bugfix(ThingFactory): Reset ThingTemplate ID for each match to avoid mismatches after playing custom maps. --- .../Code/GameEngine/Include/Common/ThingFactory.h | 1 + .../GameEngine/Source/Common/Thing/ThingFactory.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h b/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h index facde87438..861c32152c 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h @@ -124,6 +124,7 @@ class ThingFactory : public SubsystemInterface ThingTemplate *m_firstTemplate; ///< head of linked list UnsignedShort m_nextTemplateID; ///< next available ID for templates + UnsignedShort m_templateCount; ///< the value of m_nextTemplateID before loading the first map (even shellmap) ThingTemplateHashMap m_templateHashMap; ///< all thing templates, for fast lookup. diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index 1aa09afad2..8b244ea874 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -105,6 +105,7 @@ ThingFactory::ThingFactory() { m_firstTemplate = NULL; m_nextTemplateID = 1; // not zero! + m_templateCount = 0; #ifdef USING_STLPORT m_templateHashMap.resize( TEMPLATE_HASH_SIZE ); @@ -207,6 +208,8 @@ void ThingFactory::init( void ) //------------------------------------------------------------------------------------------------- void ThingFactory::reset( void ) { + UnsignedInt erased = 0; + ThingTemplate *t; // go through all templates and delete any overrides for( t = m_firstTemplate; t; /* empty */ ) @@ -234,10 +237,15 @@ void ThingFactory::reset( void ) if (stillValid == NULL) { // Also needs to be removed from the Hash map. m_templateHashMap.erase(templateName); + ++erased; } t = nextT; } + + // TheSuperHackers @bugfix Caball009 25/12/2025 Avoid mismatches by making m_nextTemplateID unique for a single match instead of unique since game launch. + DEBUG_ASSERTCRASH(m_templateIDCount + erased == m_nextTemplateID, ("Thing template ID is invalid after deleting overrides")); + m_nextTemplateID = m_templateCount; } //------------------------------------------------------------------------------------------------- @@ -542,6 +550,8 @@ void ThingFactory::postProcessLoad() } + m_templateCount = m_nextTemplateID; + #ifdef CHECK_THING_NAMES dumpMissingStringNames(); exit(0); From 67f96ad826c38ceb48f04e4b86599b089c3d32d9 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:43:58 +0100 Subject: [PATCH 2/8] Simplified thing template count assertion. --- .../Code/GameEngine/Source/Common/Thing/ThingFactory.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index 8b244ea874..e066b27473 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -208,8 +208,6 @@ void ThingFactory::init( void ) //------------------------------------------------------------------------------------------------- void ThingFactory::reset( void ) { - UnsignedInt erased = 0; - ThingTemplate *t; // go through all templates and delete any overrides for( t = m_firstTemplate; t; /* empty */ ) @@ -237,14 +235,13 @@ void ThingFactory::reset( void ) if (stillValid == NULL) { // Also needs to be removed from the Hash map. m_templateHashMap.erase(templateName); - ++erased; } t = nextT; } // TheSuperHackers @bugfix Caball009 25/12/2025 Avoid mismatches by making m_nextTemplateID unique for a single match instead of unique since game launch. - DEBUG_ASSERTCRASH(m_templateIDCount + erased == m_nextTemplateID, ("Thing template ID is invalid after deleting overrides")); + DEBUG_ASSERTCRASH(m_templateHashMap.size() + 1 == m_templateCount, ("The ThingTemplate count is invalid after deleting overrides")); m_nextTemplateID = m_templateCount; } From 0aaa74f15f95493847f36c0f83b5e01bee24caff Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:55:58 +0100 Subject: [PATCH 3/8] Simplified implementation by relying on the size of the template hash map. --- .../Code/GameEngine/Include/Common/ThingFactory.h | 1 - .../GameEngine/Source/Common/Thing/ThingFactory.cpp | 13 ++++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h b/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h index 861c32152c..facde87438 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/ThingFactory.h @@ -124,7 +124,6 @@ class ThingFactory : public SubsystemInterface ThingTemplate *m_firstTemplate; ///< head of linked list UnsignedShort m_nextTemplateID; ///< next available ID for templates - UnsignedShort m_templateCount; ///< the value of m_nextTemplateID before loading the first map (even shellmap) ThingTemplateHashMap m_templateHashMap; ///< all thing templates, for fast lookup. diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index e066b27473..c83697ea19 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -104,8 +104,7 @@ void ThingFactory::addTemplate( ThingTemplate *tmplate ) ThingFactory::ThingFactory() { m_firstTemplate = NULL; - m_nextTemplateID = 1; // not zero! - m_templateCount = 0; + m_nextTemplateID = 0; #ifdef USING_STLPORT m_templateHashMap.resize( TEMPLATE_HASH_SIZE ); @@ -146,7 +145,7 @@ ThingTemplate *ThingFactory::newTemplate( const AsciiString& name ) } // give template a unique identifier - newTemplate->friend_setTemplateID( m_nextTemplateID++ ); + newTemplate->friend_setTemplateID( ++m_nextTemplateID ); // pre-increment to use non-zero ID value DEBUG_ASSERTCRASH( m_nextTemplateID != 0, ("m_nextTemplateID wrapped to zero") ); // assign name @@ -237,12 +236,14 @@ void ThingFactory::reset( void ) m_templateHashMap.erase(templateName); } + DEBUG_ASSERTCRASH(!nextT || t->getTemplateID() == nextT->getTemplateID() + 1); + t = nextT; } // TheSuperHackers @bugfix Caball009 25/12/2025 Avoid mismatches by making m_nextTemplateID unique for a single match instead of unique since game launch. - DEBUG_ASSERTCRASH(m_templateHashMap.size() + 1 == m_templateCount, ("The ThingTemplate count is invalid after deleting overrides")); - m_nextTemplateID = m_templateCount; + DEBUG_ASSERTCRASH(m_firstTemplate && m_firstTemplate->getTemplateID() == m_templateHashMap.size(), ("Template ID is unexpected after deleting overrides")); + m_nextTemplateID = static_cast(m_templateHashMap.size()); } //------------------------------------------------------------------------------------------------- @@ -547,8 +548,6 @@ void ThingFactory::postProcessLoad() } - m_templateCount = m_nextTemplateID; - #ifdef CHECK_THING_NAMES dumpMissingStringNames(); exit(0); From 703e2d5e9d3109c71e3da40ff2cf6bb9b52b8ce2 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Mon, 29 Dec 2025 23:03:18 +0100 Subject: [PATCH 4/8] Fixed debug assertion. --- GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index c83697ea19..f9d3e6badd 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -236,7 +236,7 @@ void ThingFactory::reset( void ) m_templateHashMap.erase(templateName); } - DEBUG_ASSERTCRASH(!nextT || t->getTemplateID() == nextT->getTemplateID() + 1); + DEBUG_ASSERTCRASH(!nextT || t->getTemplateID() == nextT->getTemplateID() + 1, ("Next template ID is unexpected")); t = nextT; } From 0d3d9dd0d3de20194841c2a15ce219b76715ecdf Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Wed, 31 Dec 2025 19:04:39 +0100 Subject: [PATCH 5/8] Used template ID value from first template. --- GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index f9d3e6badd..7531084ffe 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -243,7 +243,7 @@ void ThingFactory::reset( void ) // TheSuperHackers @bugfix Caball009 25/12/2025 Avoid mismatches by making m_nextTemplateID unique for a single match instead of unique since game launch. DEBUG_ASSERTCRASH(m_firstTemplate && m_firstTemplate->getTemplateID() == m_templateHashMap.size(), ("Template ID is unexpected after deleting overrides")); - m_nextTemplateID = static_cast(m_templateHashMap.size()); + m_nextTemplateID = m_firstTemplate->getTemplateID(); } //------------------------------------------------------------------------------------------------- From d92a62c6db10a16c076e44870f714348202fdd87 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Thu, 1 Jan 2026 19:44:19 +0100 Subject: [PATCH 6/8] Reverted increment logic for 'm_nextTemplateID'. --- .../Code/GameEngine/Source/Common/Thing/ThingFactory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index 7531084ffe..47057315b4 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -104,7 +104,7 @@ void ThingFactory::addTemplate( ThingTemplate *tmplate ) ThingFactory::ThingFactory() { m_firstTemplate = NULL; - m_nextTemplateID = 0; + m_nextTemplateID = 1; // not zero! #ifdef USING_STLPORT m_templateHashMap.resize( TEMPLATE_HASH_SIZE ); @@ -145,7 +145,7 @@ ThingTemplate *ThingFactory::newTemplate( const AsciiString& name ) } // give template a unique identifier - newTemplate->friend_setTemplateID( ++m_nextTemplateID ); // pre-increment to use non-zero ID value + newTemplate->friend_setTemplateID( m_nextTemplateID++ ); DEBUG_ASSERTCRASH( m_nextTemplateID != 0, ("m_nextTemplateID wrapped to zero") ); // assign name @@ -243,7 +243,7 @@ void ThingFactory::reset( void ) // TheSuperHackers @bugfix Caball009 25/12/2025 Avoid mismatches by making m_nextTemplateID unique for a single match instead of unique since game launch. DEBUG_ASSERTCRASH(m_firstTemplate && m_firstTemplate->getTemplateID() == m_templateHashMap.size(), ("Template ID is unexpected after deleting overrides")); - m_nextTemplateID = m_firstTemplate->getTemplateID(); + m_nextTemplateID = static_cast(m_firstTemplate->getTemplateID() + 1); } //------------------------------------------------------------------------------------------------- From c4bbe1dffc95980755c8f1abe4e46d8757fbdec3 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Thu, 1 Jan 2026 19:45:58 +0100 Subject: [PATCH 7/8] Restored original code. --- GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index 47057315b4..71a9e724fb 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -104,7 +104,7 @@ void ThingFactory::addTemplate( ThingTemplate *tmplate ) ThingFactory::ThingFactory() { m_firstTemplate = NULL; - m_nextTemplateID = 1; // not zero! + m_nextTemplateID = 1; // not zero! #ifdef USING_STLPORT m_templateHashMap.resize( TEMPLATE_HASH_SIZE ); From 2756fa2fc9e98a40143bf246b85057ab4ba9c590 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 2 Jan 2026 20:37:45 +0100 Subject: [PATCH 8/8] Replicated in Generals. --- .../Code/GameEngine/Source/Common/Thing/ThingFactory.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Generals/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp b/Generals/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp index 22db98ea19..42b9e4a120 100644 --- a/Generals/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp +++ b/Generals/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp @@ -236,8 +236,14 @@ void ThingFactory::reset( void ) m_templateHashMap.erase(templateName); } + DEBUG_ASSERTCRASH(!nextT || t->getTemplateID() == nextT->getTemplateID() + 1, ("Next template ID is unexpected")); + t = nextT; } + + // TheSuperHackers @bugfix Caball009 25/12/2025 Avoid mismatches by making m_nextTemplateID unique for a single match instead of unique since game launch. + DEBUG_ASSERTCRASH(m_firstTemplate && m_firstTemplate->getTemplateID() == m_templateHashMap.size(), ("Template ID is unexpected after deleting overrides")); + m_nextTemplateID = static_cast(m_firstTemplate->getTemplateID() + 1); } //-------------------------------------------------------------------------------------------------