diff --git a/Dependencies/Utility/Utility/CppMacros.h b/Dependencies/Utility/Utility/CppMacros.h index 8bfb0297f2..570e8254ce 100644 --- a/Dependencies/Utility/Utility/CppMacros.h +++ b/Dependencies/Utility/Utility/CppMacros.h @@ -19,6 +19,10 @@ // This file contains macros to help upgrade the code for newer cpp standards. #pragma once +#if __cplusplus >= 201103L +#include +#endif + #if __cplusplus >= 201703L #define NOEXCEPT_17 noexcept #define REGISTER @@ -44,3 +48,18 @@ #define constexpr #define nullptr 0 #endif + +// Helper to move-assign from reference: uses std::move in C++11, swap in C++98 +template +inline void move_or_swap(T& dest, T& src) +{ +#if __cplusplus >= 201103L + dest = std::move(src); +#else + // C++03 fallback: mimic move semantics + // dest gets src's value, src becomes empty + T empty; + dest.swap(src); + src.swap(empty); +#endif +} diff --git a/Generals/Code/GameEngine/Include/GameLogic/AI.h b/Generals/Code/GameEngine/Include/GameLogic/AI.h index dc2053d4cc..5e02c9096d 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AI.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AI.h @@ -536,18 +536,18 @@ class AICommandInterface aiDoCommand(&parms); } - void aiFollowExitProductionPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - parms.m_coords = *path; + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } - void aiFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - parms.m_coords = *path; + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 03f0de0e73..7e39c8ec7c 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/Generals/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -138,7 +138,7 @@ class AIStateMachine : public StateMachine virtual StateReturnType setState( StateID newStateID ); /// @todo Rethink state parameter passing. Continuing in this fashion will have a pile of params in the machine (MSB) - void setGoalPath( const std::vector* path ); + void setGoalPath( std::vector* path ); void addToGoalPath( const Coord3D *pathPoint ); const Coord3D *getGoalPathPosition( Int i ) const; ///< return path position at index "i" Int getGoalPathSize() const { return m_goalPath.size(); } diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h index 0482f737aa..b47f353ecf 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h @@ -244,7 +244,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual void privateFollowWaypointPathAsTeam( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathAsTeamExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object virtual void privateForceAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object @@ -338,7 +338,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual Bool isBusy() const; virtual void onObjectCreated(); - virtual void doQuickExit( const std::vector* path ); ///< get out of this Object + virtual void doQuickExit( std::vector* path ); ///< get out of this Object virtual void aiDoCommand(const AICommandParms* parms); diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h index cc6f8c4e72..3c8579ebf1 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h @@ -104,7 +104,7 @@ class JetAIUpdate : public AIUpdateInterface Real friend_getMinHeight() const { return getJetAIUpdateModuleData()->m_minHeight; } Real friend_getParkingOffset() const { return getJetAIUpdateModuleData()->m_parkingOffset; } UnsignedInt friend_getTakeoffPause() const { return getJetAIUpdateModuleData()->m_takeoffPause; } - void friend_setGoalPath( const std::vector* path ) { getStateMachine()->setGoalPath(path); } + void friend_setGoalPath( std::vector* path ) { getStateMachine()->setGoalPath(path); } void friend_setTakeoffInProgress(Bool v) { setFlag(TAKEOFF_IN_PROGRESS, v); } void friend_setLandingInProgress(Bool v) { setFlag(LANDING_IN_PROGRESS, v); } void friend_setTaxiInProgress(Bool v) { setFlag(TAXI_IN_PROGRESS, v); } @@ -122,7 +122,7 @@ class JetAIUpdate : public AIUpdateInterface virtual AIStateMachine* makeStateMachine(); - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateEnter( Object *obj, CommandSourceType cmdSource ); ///< enter the given object virtual void privateGetRepaired( Object *repairDepot, CommandSourceType cmdSource );///< get repaired at repair depot diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 05ce1ea359..ae0f18d0c7 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -95,7 +95,10 @@ void AICommandParmsStorage::store(const AICommandParms& parms) m_obj = parms.m_obj ? parms.m_obj->getID() : INVALID_ID; m_otherObj = parms.m_otherObj ? parms.m_otherObj->getID() : INVALID_ID; m_teamName = parms.m_team ? parms.m_team->getName() : AsciiString::TheEmptyString; - m_coords = parms.m_coords; + // We intentionally const_cast here so we can move the path coordinates into storage. + // AICommandParms is treated as a transient command container that is not reused after dispatch. + std::vector& coords = const_cast&>(parms.m_coords); + move_or_swap(m_coords, coords); m_waypoint = parms.m_waypoint; m_polygon = parms.m_polygon; m_intValue = parms.m_intValue; /// misc usage @@ -816,9 +819,9 @@ void AIStateMachine::loadPostProcess( void ) /** * Define a simple path */ -void AIStateMachine::setGoalPath( const std::vector* path ) +void AIStateMachine::setGoalPath( std::vector* path ) { - m_goalPath = *path; + move_or_swap(m_goalPath, *path); } #ifdef STATE_MACHINE_DEBUG diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 678d87cfeb..602814c410 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2619,14 +2619,22 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, FALSE); break; + } case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the exit path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, TRUE); break; + } case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); break; @@ -3240,7 +3248,7 @@ void AIUpdateInterface::privateFollowPathAppend( const Coord3D *pos, CommandSour /** * Follow the path defined by the given array of points */ -void AIUpdateInterface::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void AIUpdateInterface::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (getObject()->isMobile() == FALSE) return; @@ -3681,7 +3689,7 @@ void AIUpdateInterface::privateExit( Object *objectToExit, CommandSourceType cmd /** * Get out of whatever it is inside of */ -void AIUpdateInterface::doQuickExit( const std::vector* path ) +void AIUpdateInterface::doQuickExit( std::vector* path ) { Bool locked = getStateMachine()->isLocked(); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp index f264228618..1ce63cffc5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp @@ -2172,7 +2172,7 @@ Bool JetAIUpdate::getTreatAsAircraftForLocoDistToGoal() const /** * Follow the path defined by the given array of points */ -void JetAIUpdate::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void JetAIUpdate::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (exitProduction) { diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h index 23cf4f94f8..00bf02666f 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AI.h @@ -550,18 +550,18 @@ class AICommandInterface aiDoCommand(&parms); } - void aiFollowExitProductionPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowExitProductionPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_EXITPRODUCTION_PATH, cmdSource); - parms.m_coords = *path; + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } - void aiFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) + inline void aiFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource ) { AICommandParms parms(AICMD_FOLLOW_PATH, cmdSource); - parms.m_coords = *path; + move_or_swap(parms.m_coords, *path); parms.m_obj = ignoreObject; aiDoCommand(&parms); } diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h index 3171df36bc..8d96e65997 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIStateMachine.h @@ -141,7 +141,7 @@ class AIStateMachine : public StateMachine virtual StateReturnType setState( StateID newStateID ); /// @todo Rethink state parameter passing. Continuing in this fashion will have a pile of params in the machine (MSB) - void setGoalPath( const std::vector* path ); + void setGoalPath( std::vector* path ); void addToGoalPath( const Coord3D *pathPoint ); const Coord3D *getGoalPathPosition( Int i ) const; ///< return path position at index "i" Int getGoalPathSize() const { return m_goalPath.size(); } diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h index 423977192c..32e562d23a 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h @@ -249,7 +249,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual void privateFollowWaypointPathAsTeam( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point virtual void privateFollowWaypointPathAsTeamExact( const Waypoint *way, CommandSourceType cmdSource );///< start following the path from the given point - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object virtual void privateForceAttackObject( Object *victim, Int maxShotsToFire, CommandSourceType cmdSource ); ///< attack given object @@ -351,7 +351,7 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface virtual Bool isBusy() const; virtual void onObjectCreated(); - virtual void doQuickExit( const std::vector* path ); ///< get out of this Object + virtual void doQuickExit( std::vector* path ); ///< get out of this Object virtual void aiDoCommand(const AICommandParms* parms); diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h index 1840d30a4b..a7cd1157aa 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/JetAIUpdate.h @@ -110,7 +110,7 @@ class JetAIUpdate : public AIUpdateInterface Real friend_getMinHeight() const { return getJetAIUpdateModuleData()->m_minHeight; } Real friend_getParkingOffset() const { return getJetAIUpdateModuleData()->m_parkingOffset; } UnsignedInt friend_getTakeoffPause() const { return getJetAIUpdateModuleData()->m_takeoffPause; } - void friend_setGoalPath( const std::vector* path ) { getStateMachine()->setGoalPath(path); } + void friend_setGoalPath( std::vector* path ) { getStateMachine()->setGoalPath(path); } void friend_setTakeoffInProgress(Bool v) { setFlag(TAKEOFF_IN_PROGRESS, v); } void friend_setLandingInProgress(Bool v) { setFlag(LANDING_IN_PROGRESS, v); } void friend_setTaxiInProgress(Bool v) { setFlag(TAXI_IN_PROGRESS, v); } @@ -131,7 +131,7 @@ class JetAIUpdate : public AIUpdateInterface virtual AIStateMachine* makeStateMachine(); - virtual void privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points + virtual void privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction );///< follow the path defined by the given array of points virtual void privateFollowPathAppend( const Coord3D *pos, CommandSourceType cmdSource ); virtual void privateEnter( Object *obj, CommandSourceType cmdSource ); ///< enter the given object virtual void privateGetRepaired( Object *repairDepot, CommandSourceType cmdSource );///< get repaired at repair depot diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 63b3474662..1e4c818c5e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -98,7 +98,10 @@ void AICommandParmsStorage::store(const AICommandParms& parms) m_obj = parms.m_obj ? parms.m_obj->getID() : INVALID_ID; m_otherObj = parms.m_otherObj ? parms.m_otherObj->getID() : INVALID_ID; m_teamName = parms.m_team ? parms.m_team->getName() : AsciiString::TheEmptyString; - m_coords = parms.m_coords; + // We intentionally const_cast here so we can move the path coordinates into storage. + // AICommandParms is treated as a transient command container that is not reused after dispatch. + std::vector& coords = const_cast&>(parms.m_coords); + move_or_swap(m_coords, coords); m_waypoint = parms.m_waypoint; m_polygon = parms.m_polygon; m_intValue = parms.m_intValue; /// misc usage @@ -821,9 +824,9 @@ void AIStateMachine::loadPostProcess( void ) /** * Define a simple path */ -void AIStateMachine::setGoalPath( const std::vector* path ) +void AIStateMachine::setGoalPath( std::vector* path ) { - m_goalPath = *path; + move_or_swap(m_goalPath, *path); } #ifdef STATE_MACHINE_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index bfc97640c3..9e0d58d4ce 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2681,14 +2681,22 @@ void AIUpdateInterface::aiDoCommand(const AICommandParms* parms) privateFollowWaypointPathAsTeamExact(parms->m_waypoint, parms->m_cmdSource); break; case AICMD_FOLLOW_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, FALSE); break; + } case AICMD_FOLLOW_PATH_APPEND: privateFollowPathAppend(&parms->m_pos, parms->m_cmdSource); break; case AICMD_FOLLOW_EXITPRODUCTION_PATH: - privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, TRUE); + { + // Keep AICommandParms const; use a local copy of the coordinates when following the exit path. + std::vector coords = parms->m_coords; + privateFollowPath(&coords, parms->m_obj, parms->m_cmdSource, TRUE); break; + } case AICMD_ATTACK_OBJECT: privateAttackObject(parms->m_obj, parms->m_intValue, parms->m_cmdSource); break; @@ -3377,7 +3385,7 @@ void AIUpdateInterface::privateFollowPathAppend( const Coord3D *pos, CommandSour /** * Follow the path defined by the given array of points */ -void AIUpdateInterface::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void AIUpdateInterface::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (getObject()->isMobile() == FALSE) return; @@ -3869,7 +3877,7 @@ void AIUpdateInterface::privateExitInstantly( Object *objectToExit, CommandSourc /** * Get out of whatever it is inside of */ -void AIUpdateInterface::doQuickExit( const std::vector* path ) +void AIUpdateInterface::doQuickExit( std::vector* path ) { Bool locked = getStateMachine()->isLocked(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp index 4e3b24a426..dc2a4162b7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp @@ -2399,7 +2399,7 @@ Bool JetAIUpdate::getTreatAsAircraftForLocoDistToGoal() const /** * Follow the path defined by the given array of points */ -void JetAIUpdate::privateFollowPath( const std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) +void JetAIUpdate::privateFollowPath( std::vector* path, Object *ignoreObject, CommandSourceType cmdSource, Bool exitProduction ) { if (exitProduction) {