diff --git a/Generals/Code/GameEngine/Source/GameClient/GameClient.cpp b/Generals/Code/GameEngine/Source/GameClient/GameClient.cpp index 9f7742976d4..214fc9f7263 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GameClient.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GameClient.cpp @@ -433,7 +433,6 @@ void GameClient::init() /** Reset the game client for a new game */ void GameClient::reset() { - Drawable *draw, *nextDraw; m_drawableHash.clear(); #if USING_STLPORT m_drawableHash.resize(DRAWABLE_HASH_SIZE); @@ -445,7 +444,7 @@ void GameClient::reset() TheInGameUI->reset(); // destroy all Drawables - for( draw = m_drawableList; draw; draw = nextDraw ) + for( Drawable *draw = m_drawableList, *nextDraw = nullptr; draw; draw = nextDraw ) { nextDraw = draw->getNextDrawable(); destroyDrawable( draw ); @@ -801,7 +800,6 @@ void GameClient::updateFakeDrawables() /** ----------------------------------------------------------------------------------------------- * Given an object id, return the associated object. - * For efficiency, a small Least Recently Used cache is incorporated. * This method is the primary interface for accessing objects, and should be used * instead of pointers to "attach" objects to each other. */ @@ -860,7 +858,7 @@ void GameClient::addDrawableToLookupTable(Drawable *draw ) if( draw == nullptr ) return; - // add to lookup + // add to lookup table m_drawableHash[ draw->getID() ] = draw; } @@ -875,7 +873,7 @@ void GameClient::removeDrawableFromLookupTable( Drawable *draw ) if( draw == nullptr ) return; - // remove from table + // remove from lookup table m_drawableHash.erase( draw->getID() ); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 09048b600d6..68e5efad0fd 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -3444,7 +3444,7 @@ void GameLogic::addObjectToLookupTable( Object *obj ) if( obj == nullptr ) return; - // add to lookup + // add to lookup table m_objHash[ obj->getID() ] = obj; } diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameClient.h b/GeneralsMD/Code/GameEngine/Include/GameClient/GameClient.h index c4e6b7a7492..bcc48e51b20 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/GameClient.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/GameClient.h @@ -57,10 +57,8 @@ class SnowManager; /// Function pointers for use by GameClient callback functions. typedef void (*GameClientFuncPtr)( Drawable *draw, void *userData ); -//typedef std::hash_map, rts::equal_to > DrawablePtrHash; -//typedef DrawablePtrHash::iterator DrawablePtrHashIt; - -typedef std::vector DrawablePtrVector; +typedef std::hash_map, rts::equal_to/**/> DrawablePtrHash; +typedef DrawablePtrHash::iterator DrawablePtrHashIt; //----------------------------------------------------------------------------- /** The Client message dispatcher, this is the last "translator" on the message @@ -170,8 +168,7 @@ class GameClient : public SubsystemInterface, UnsignedInt m_frame; ///< Simulation frame number from server Drawable *m_drawableList; ///< All of the drawables in the world -// DrawablePtrHash m_drawableHash; ///< Used for DrawableID lookups - DrawablePtrVector m_drawableVector; + DrawablePtrHash m_drawableHash; ///< Used for DrawableID lookups DrawableID m_nextDrawableID; ///< For allocating drawable id's DrawableID allocDrawableID(); ///< Returns a new unique drawable id @@ -237,30 +234,6 @@ class GameClient : public SubsystemInterface, } \ } while (0); -/** ----------------------------------------------------------------------------------------------- - * Given an object id, return the associated object. - * This method is the primary interface for accessing objects, and should be used - * instead of pointers to "attach" objects to each other. - */ -inline Drawable* GameClient::findDrawableByID( const DrawableID id ) -{ - if( id == INVALID_DRAWABLE_ID ) - return nullptr; - -// DrawablePtrHashIt it = m_drawableHash.find(id); -// if (it == m_drawableHash.end()) { -// // no such drawable -// return nullptr; -// } -// -// return (*it).second; - - if( (size_t)id < m_drawableVector.size() ) - return m_drawableVector[(size_t)id]; - - return nullptr; -} - // the singleton extern GameClient *TheGameClient; diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h index 15276811ccd..898f23b2cf8 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h @@ -78,8 +78,8 @@ enum /// Function pointers for use by GameLogic callback functions. typedef void (*GameLogicFuncPtr)( Object *obj, void *userData ); -//typedef std::hash_map, rts::equal_to > ObjectPtrHash; -//typedef ObjectPtrHash::const_iterator ObjectPtrIter; +typedef std::hash_map, rts::equal_to/**/> ObjectPtrHash; +typedef ObjectPtrHash::const_iterator ObjectPtrIter; typedef std::vector ObjectPtrVector; @@ -401,8 +401,7 @@ class GameLogic : public SubsystemInterface, public Snapshot WindowLayout *m_background; Object* m_objList; ///< All of the objects in the world. -// ObjectPtrHash m_objHash; ///< Used for ObjectID lookups - ObjectPtrVector m_objVector; + ObjectPtrHash m_objHash; ///< Used for ObjectID lookups // this is a vector, but is maintained as a priority queue. // never modify it directly; please use the proper access methods. @@ -503,15 +502,11 @@ inline Object* GameLogic::findObjectByID( ObjectID id ) if( id == INVALID_ID ) return nullptr; -// ObjectPtrHash::iterator it = m_objHash.find(id); -// if (it == m_objHash.end()) -// return nullptr; -// -// return (*it).second; - if( (size_t)id < m_objVector.size() ) - return m_objVector[(size_t)id]; + ObjectPtrHash::iterator it = m_objHash.find(id); + if (it == m_objHash.end()) + return nullptr; - return nullptr; + return (*it).second; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp index 983845c6e0d..9b6f5ebe70c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp @@ -453,18 +453,18 @@ void GameClient::init() /** Reset the game client for a new game */ void GameClient::reset() { - Drawable *draw, *nextDraw; -// m_drawableHash.clear(); -// m_drawableHash.resize(DRAWABLE_HASH_SIZE); - - m_drawableVector.clear(); - m_drawableVector.resize(DRAWABLE_HASH_SIZE, nullptr); + m_drawableHash.clear(); +#if USING_STLPORT + m_drawableHash.resize(DRAWABLE_HASH_SIZE); +#else + m_drawableHash.reserve(DRAWABLE_HASH_SIZE); +#endif // need to reset the in game UI to clear drawables before they are destroyed TheInGameUI->reset(); // destroy all Drawables - for( draw = m_drawableList; draw; draw = nextDraw ) + for( Drawable *draw = m_drawableList, *nextDraw = nullptr; draw; draw = nextDraw ) { nextDraw = draw->getNextDrawable(); destroyDrawable( draw ); @@ -849,6 +849,22 @@ void GameClient::updateFakeDrawables() } } +/** ----------------------------------------------------------------------------------------------- + * Given an object id, return the associated object. + * This method is the primary interface for accessing objects, and should be used + * instead of pointers to "attach" objects to each other. + */ +Drawable* GameClient::findDrawableByID( const DrawableID id ) +{ + DrawablePtrHashIt it = m_drawableHash.find(id); + if (it == m_drawableHash.end()) { + // no such drawable + return nullptr; + } + + return (*it).second; +} + /** ----------------------------------------------------------------------------------------------- * Destroy the drawable immediately. */ @@ -893,13 +909,8 @@ void GameClient::addDrawableToLookupTable(Drawable *draw ) if( draw == nullptr ) return; - // add to lookup -// m_drawableHash[ draw->getID() ] = draw; - DrawableID newID = draw->getID(); - while( newID >= m_drawableVector.size() ) // Fail case is hella rare, so faster to double up on size() call - m_drawableVector.resize(m_drawableVector.size() * 2, nullptr); - - m_drawableVector[ newID ] = draw; + // add to lookup table + m_drawableHash[ draw->getID() ] = draw; } @@ -910,13 +921,11 @@ void GameClient::removeDrawableFromLookupTable( Drawable *draw ) { // sanity - // TheSuperHackers @fix Mauller/Xezon 24/04/2025 Prevent out of range access to vector lookup table - if( draw == nullptr || static_cast(draw->getID()) >= m_drawableVector.size() ) + if( draw == nullptr ) return; - // remove from table -// m_drawableHash.erase( draw->getID() ); - m_drawableVector[ draw->getID() ] = nullptr; + // remove from lookup table + m_drawableHash.erase( draw->getID() ); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 0d8d4e64692..e9c5b1b9bab 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -311,8 +311,7 @@ void GameLogic::destroyAllObjectsImmediate() processDestroyList(); DEBUG_ASSERTCRASH( m_objList == nullptr, ("destroyAllObjectsImmediate: Object list not cleared") ); -// m_objHash.clear(); - m_objVector.clear(); + m_objHash.clear(); } @@ -422,8 +421,11 @@ void GameLogic::reset() destroyAllObjectsImmediate(); // set the hash to be rather large. We need to optimize this value later. -// m_objHash.resize(OBJ_HASH_SIZE); - m_objVector.resize(OBJ_HASH_SIZE, nullptr); +#if USING_STLPORT + m_objHash.resize(OBJ_HASH_SIZE); +#else + m_objHash.reserve(OBJ_HASH_SIZE); +#endif m_nextObjID = (ObjectID)1; @@ -3977,13 +3979,8 @@ void GameLogic::addObjectToLookupTable( Object *obj ) if( obj == nullptr ) return; - // add to lookup -// m_objHash[ obj->getID() ] = obj; - ObjectID newID = obj->getID(); - while( newID >= m_objVector.size() ) // Fail case is hella rare, so faster to double up on size() call - m_objVector.resize(m_objVector.size() * 2, nullptr); - - m_objVector[ newID ] = obj; + // add to lookup table + m_objHash[ obj->getID() ] = obj; } @@ -3994,13 +3991,11 @@ void GameLogic::removeObjectFromLookupTable( Object *obj ) { // sanity - // TheSuperHackers @fix Mauller/Xezon 24/04/2025 Prevent out of range access to vector lookup table - if( obj == nullptr || static_cast(obj->getID()) >= m_objVector.size() ) + if( obj == nullptr ) return; // remove from lookup table -// m_objHash.erase( obj->getID() ); - m_objVector[ obj->getID() ] = nullptr; + m_objHash.erase( obj->getID() ); }