From 522bf60ad1176ff9960f4f1e77794b23242ab15d Mon Sep 17 00:00:00 2001 From: rtri Date: Sun, 28 May 2017 01:49:22 +0200 Subject: [PATCH] fix #5575 --- rts/ExternalAI/EngineOutHandler.cpp | 240 ++++++++++---------- rts/ExternalAI/EngineOutHandler.h | 14 +- rts/System/LoadSave/CregLoadSaveHandler.cpp | 71 +++--- rts/System/LoadSave/LuaLoadSaveHandler.cpp | 29 ++- 4 files changed, 180 insertions(+), 174 deletions(-) diff --git a/rts/ExternalAI/EngineOutHandler.cpp b/rts/ExternalAI/EngineOutHandler.cpp index c359bd1c05f..176af918c63 100644 --- a/rts/ExternalAI/EngineOutHandler.cpp +++ b/rts/ExternalAI/EngineOutHandler.cpp @@ -31,22 +31,22 @@ CR_REG_METADATA(CEngineOutHandler, ( // "constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) // [with _T1 = const unsigned char; _T2 = std::unique_ptr]’ // is implicitly deleted because the default definition would be ill-formed" - CR_IGNORED(id_skirmishAI), - CR_MEMBER(team_skirmishAIs) + CR_IGNORED(hostSkirmishAIs), + CR_MEMBER(teamSkirmishAIs) )) static inline bool IsUnitInLosOrRadarOfAllyTeam(const CUnit& unit, const int allyTeamId) { // NOTE: - // we check for globalLOS because the LOS-state of a - // new unit has not yet been set when it is created - // (thus UnitCreated will not produce EnemyCreated, - // etc. without this, even when globalLOS is enabled - // (for non-cheating AI's)) + // we check for globalLOS because the LOS-state of a + // new unit has not yet been set when it is created + // (thus UnitCreated will not produce EnemyCreated, + // etc. without this, even when globalLOS is enabled + // (for non-cheating AI's)) return (losHandler->globalLOS[allyTeamId] || (unit.losStatus[allyTeamId] & (LOS_INLOS | LOS_INRADAR))); } -static CEngineOutHandler* singleton = NULL; +static CEngineOutHandler* singleton = nullptr; static unsigned int numInstances = 0; CEngineOutHandler* CEngineOutHandler::GetInstance() { @@ -58,14 +58,14 @@ CEngineOutHandler* CEngineOutHandler::GetInstance() { } void CEngineOutHandler::Create() { - if (singleton == NULL) { + if (singleton == nullptr) { singleton = new CEngineOutHandler(); numInstances += 1; } } void CEngineOutHandler::Destroy() { - if (singleton != NULL) { + if (singleton != nullptr) { singleton->PreDestroy(); spring::SafeDelete(singleton); @@ -77,24 +77,24 @@ void CEngineOutHandler::Destroy() { CEngineOutHandler::~CEngineOutHandler() { - // id_skirmishAI should be empty already, but this can not hurt + // hostSkirmishAIs should be empty already, but this can not hurt // (it releases only those AI's that were not already released) - while (!id_skirmishAI.empty()) { - DestroySkirmishAI((id_skirmishAI.begin())->first); + while (!hostSkirmishAIs.empty()) { + DestroySkirmishAI((hostSkirmishAIs.begin())->first); } } // This macro should be insterted at the start of each method sending AI events -#define AI_EVT_MTH() \ - if (id_skirmishAI.empty()) \ - return; \ +#define AI_EVT_MTH() \ + if (hostSkirmishAIs.empty()) \ + return; \ SCOPED_TIMER("AI"); -#define DO_FOR_SKIRMISH_AIS(FUNC) \ - for (auto& ai: id_skirmishAI) { \ - (ai.second)->FUNC; \ +#define DO_FOR_SKIRMISH_AIS(FUNC) \ + for (auto& ai: hostSkirmishAIs) { \ + (ai.second)->FUNC; \ } @@ -106,16 +106,26 @@ void CEngineOutHandler::PreDestroy() { DO_FOR_SKIRMISH_AIS(PreDestroy()) } -void CEngineOutHandler::Load(std::istream* s, const size_t skirmishAIId) { +void CEngineOutHandler::Load(std::istream* s, const uint8_t skirmishAIId) { AI_EVT_MTH(); - id_skirmishAI[skirmishAIId]->Load(s); + const auto it = hostSkirmishAIs.find(skirmishAIId); + + if (it == hostSkirmishAIs.end()) + return; + + (it->second)->Load(s); } -void CEngineOutHandler::Save(std::ostream* s, const size_t skirmishAIId) { +void CEngineOutHandler::Save(std::ostream* s, const uint8_t skirmishAIId) { AI_EVT_MTH(); - id_skirmishAI[skirmishAIId]->Save(s); + const auto it = hostSkirmishAIs.find(skirmishAIId); + + if (it == hostSkirmishAIs.end()) + return; + + (it->second)->Save(s); } @@ -133,10 +143,10 @@ void CEngineOutHandler::Update() { // everything about it anyway, and do not need to be informed #define DO_FOR_ALLIED_SKIRMISH_AIS(FUNC, ALLY_TEAM_ID, UNIT_ALLY_TEAM_ID) \ if (!teamHandler->Ally(ALLY_TEAM_ID, UNIT_ALLY_TEAM_ID)) { \ - for (auto& ai: id_skirmishAI) { \ - const int aiAllyTeam = teamHandler->AllyTeam((ai.second)->GetTeamId()); \ + for (auto& p: hostSkirmishAIs) { \ + const int aiAllyTeam = teamHandler->AllyTeam((p.second)->GetTeamId()); \ if (teamHandler->Ally(aiAllyTeam, ALLY_TEAM_ID)) { \ - (ai.second)->FUNC; \ + (p.second)->FUNC; \ } \ } \ } @@ -180,31 +190,31 @@ void CEngineOutHandler::UnitLeftRadar(const CUnit& unit, int allyTeamId) { -#define DO_FOR_TEAM_SKIRMISH_AIS(FUNC, TEAM_ID) \ - if (team_skirmishAIs.find(TEAM_ID) == team_skirmishAIs.end()) \ - return; \ - \ - for (auto ai: team_skirmishAIs[TEAM_ID]) { \ - id_skirmishAI[ai]->FUNC; \ - } \ +#define DO_FOR_TEAM_SKIRMISH_AIS(FUNC, TEAM_ID) \ + if (teamSkirmishAIs.find(TEAM_ID) == teamSkirmishAIs.end()) \ + return; \ + \ + for (uint8_t aiID: teamSkirmishAIs[TEAM_ID]) { \ + hostSkirmishAIs[aiID]->FUNC; \ + } \ // Send to all teams which the unit is not allied to, // and which have cheat-events enabled, or the unit in sensor range. #define DO_FOR_ENEMY_SKIRMISH_AIS(FUNC, ALLY_TEAM_ID, UNIT) \ - for (auto& ai: id_skirmishAI) { \ - CSkirmishAIWrapper* saw = (ai.second).get(); \ + for (auto& p: hostSkirmishAIs) { \ + CSkirmishAIWrapper* aiWrapper = (p.second).get(); \ \ - const int aiAllyTeam = teamHandler->AllyTeam(saw->GetTeamId()); \ + const int aiAllyTeam = teamHandler->AllyTeam(aiWrapper->GetTeamId()); \ \ const bool alliedAI = teamHandler->Ally(aiAllyTeam, ALLY_TEAM_ID); \ - const bool cheatingAI = saw->IsCheatEventsEnabled(); \ + const bool cheatingAI = aiWrapper->IsCheatEventsEnabled(); \ \ if (alliedAI) \ continue; \ if (cheatingAI || IsUnitInLosOrRadarOfAllyTeam(UNIT, aiAllyTeam)) { \ - saw->FUNC; \ + aiWrapper->FUNC; \ } \ } @@ -260,10 +270,10 @@ void CEngineOutHandler::UnitGiven(const CUnit& unit, int oldTeam, int newTeam) { const int newAllyTeamId = unit.allyteam; const int oldAllyTeamId = teamHandler->AllyTeam(oldTeam); - for (auto& ai: id_skirmishAI) { - CSkirmishAIWrapper* saw = (ai.second).get(); + for (auto& p: hostSkirmishAIs) { + CSkirmishAIWrapper* aiWrapper = (p.second).get(); - const int aiTeam = saw->GetTeamId(); + const int aiTeam = aiWrapper->GetTeamId(); const int aiAllyTeam = teamHandler->AllyTeam(aiTeam); const bool alliedOld = teamHandler->Ally(aiAllyTeam, oldAllyTeamId); const bool alliedNew = teamHandler->Ally(aiAllyTeam, newAllyTeamId); @@ -277,14 +287,14 @@ void CEngineOutHandler::UnitGiven(const CUnit& unit, int oldTeam, int newTeam) { informAI = false; informAI |= alliedOld; informAI |= alliedNew; - informAI |= saw->IsCheatEventsEnabled(); + informAI |= aiWrapper->IsCheatEventsEnabled(); informAI |= IsUnitInLosOrRadarOfAllyTeam(unit, aiAllyTeam); } if (!informAI) continue; - saw->UnitGiven(unitId, oldTeam, newTeam); + aiWrapper->UnitGiven(unitId, oldTeam, newTeam); } } @@ -295,10 +305,10 @@ void CEngineOutHandler::UnitCaptured(const CUnit& unit, int oldTeam, int newTeam const int newAllyTeamId = unit.allyteam; const int oldAllyTeamId = teamHandler->AllyTeam(oldTeam); - for (auto& ai: id_skirmishAI) { - CSkirmishAIWrapper* saw = (ai.second).get(); + for (auto& p: hostSkirmishAIs) { + CSkirmishAIWrapper* aiWrapper = (p.second).get(); - const int aiTeam = saw->GetTeamId(); + const int aiTeam = aiWrapper->GetTeamId(); const int aiAllyTeam = teamHandler->AllyTeam(aiTeam); const bool alliedOld = teamHandler->Ally(aiAllyTeam, oldAllyTeamId); @@ -313,14 +323,14 @@ void CEngineOutHandler::UnitCaptured(const CUnit& unit, int oldTeam, int newTeam informAI = false; informAI |= alliedOld; informAI |= alliedNew; - informAI |= saw->IsCheatEventsEnabled(); + informAI |= aiWrapper->IsCheatEventsEnabled(); informAI |= IsUnitInLosOrRadarOfAllyTeam(unit, aiAllyTeam); } if (!informAI) continue; - saw->UnitCaptured(unitId, oldTeam, newTeam); + aiWrapper->UnitCaptured(unitId, oldTeam, newTeam); } } @@ -332,39 +342,39 @@ void CEngineOutHandler::UnitDestroyed(const CUnit& destroyed, const CUnit* attac const int dt = destroyed.team; // inform destroyed units team (not allies) - if (team_skirmishAIs.find(dt) != team_skirmishAIs.end()) { + if (teamSkirmishAIs.find(dt) != teamSkirmishAIs.end()) { const bool attackerInLosOrRadar = attacker && IsUnitInLosOrRadarOfAllyTeam(*attacker, destroyed.allyteam); - for (auto ai: team_skirmishAIs[dt]) { - CSkirmishAIWrapper* saw = id_skirmishAI[ai].get(); + for (uint8_t aiID: teamSkirmishAIs[dt]) { + CSkirmishAIWrapper* aiWrapper = hostSkirmishAIs[aiID].get(); int visibleAttackerId = -1; - if (attackerInLosOrRadar || saw->IsCheatEventsEnabled()) { + if (attackerInLosOrRadar || aiWrapper->IsCheatEventsEnabled()) visibleAttackerId = attackerId; - } - saw->UnitDestroyed(destroyedId, visibleAttackerId); + + aiWrapper->UnitDestroyed(destroyedId, visibleAttackerId); } } // inform all enemy teams - for (auto& ai: id_skirmishAI) { - CSkirmishAIWrapper* saw = (ai.second).get(); + for (auto& p: hostSkirmishAIs) { + CSkirmishAIWrapper* aiWrapper = (p.second).get(); - const int aiTeam = saw->GetTeamId(); + const int aiTeam = aiWrapper->GetTeamId(); const int aiAllyTeam = teamHandler->AllyTeam(aiTeam); if (teamHandler->Ally(aiAllyTeam, destroyed.allyteam)) continue; - if (!saw->IsCheatEventsEnabled() && !IsUnitInLosOrRadarOfAllyTeam(destroyed, aiAllyTeam)) + if (!aiWrapper->IsCheatEventsEnabled() && !IsUnitInLosOrRadarOfAllyTeam(destroyed, aiAllyTeam)) continue; int myAttackerId = -1; - if ((attacker != NULL) && teamHandler->Ally(aiAllyTeam, attacker->allyteam)) { + if ((attacker != nullptr) && teamHandler->Ally(aiAllyTeam, attacker->allyteam)) myAttackerId = attackerId; - } - saw->EnemyDestroyed(destroyedId, myAttackerId); + + aiWrapper->EnemyDestroyed(destroyedId, myAttackerId); } } @@ -384,48 +394,46 @@ void CEngineOutHandler::UnitDamaged( const int attackerUnitId = attacker ? attacker->id : -1; // inform damaged units team (not allies) - if (team_skirmishAIs.find(dt) != team_skirmishAIs.end()) { - float3 attackDir_damagedsView = ZeroVector; - if (attacker) { - attackDir_damagedsView = - attacker->GetErrorPos(damaged.allyteam) - - damaged.pos; - attackDir_damagedsView.ANormalize(); - } + if (teamSkirmishAIs.find(dt) != teamSkirmishAIs.end()) { + float3 attackeeDir; + + if (attacker != nullptr) + attackeeDir = (attacker->GetErrorPos(damaged.allyteam) - damaged.pos).ANormalize(); const bool attackerInLosOrRadar = attacker && IsUnitInLosOrRadarOfAllyTeam(*attacker, damaged.allyteam); - for (auto ai: team_skirmishAIs[dt]) { - const CSkirmishAIWrapper* saw = id_skirmishAI[ai].get(); + for (uint8_t aiID: teamSkirmishAIs[dt]) { + CSkirmishAIWrapper* aiWrapper = hostSkirmishAIs[aiID].get(); + int visibleAttackerUnitId = -1; - if (attackerInLosOrRadar || saw->IsCheatEventsEnabled()) + if (attackerInLosOrRadar || aiWrapper->IsCheatEventsEnabled()) visibleAttackerUnitId = attackerUnitId; - id_skirmishAI[ai]->UnitDamaged(damagedUnitId, visibleAttackerUnitId, damage, attackDir_damagedsView, weaponDefID, paralyzer); + aiWrapper->UnitDamaged(damagedUnitId, visibleAttackerUnitId, damage, attackeeDir, weaponDefID, paralyzer); } } // inform attacker units team (not allies) - if (attacker) { + if (attacker != nullptr) { const int at = attacker ? attacker->team : -1; if (teamHandler->Ally(attacker->allyteam, damaged.allyteam)) return; - if (team_skirmishAIs.find(at) == team_skirmishAIs.end()) + if (teamSkirmishAIs.find(at) == teamSkirmishAIs.end()) return; // direction from the attacker's view - const float3 attackDir = (attacker->pos - damaged.GetErrorPos(attacker->allyteam)).ANormalize(); + const float3 attackerDir = (attacker->pos - damaged.GetErrorPos(attacker->allyteam)).ANormalize(); const bool damagedInLosOrRadar = IsUnitInLosOrRadarOfAllyTeam(damaged, attacker->allyteam); - for (auto ai: team_skirmishAIs[at]) { - CSkirmishAIWrapper* saw = id_skirmishAI[ai].get(); + for (uint8_t aiID: teamSkirmishAIs[at]) { + CSkirmishAIWrapper* aiWrapper = hostSkirmishAIs[aiID].get(); + + if (!damagedInLosOrRadar && !aiWrapper->IsCheatEventsEnabled()) + continue; - if (damagedInLosOrRadar || saw->IsCheatEventsEnabled()) { - saw->EnemyDamaged(damagedUnitId, attackerUnitId, damage, - attackDir, weaponDefID, paralyzer); - } + aiWrapper->EnemyDamaged(damagedUnitId, attackerUnitId, damage, attackerDir, weaponDefID, paralyzer); } } } @@ -484,40 +492,38 @@ void CEngineOutHandler::SendChatMessage(const char* msg, int fromPlayerId) { bool CEngineOutHandler::SendLuaMessages(int aiTeam, const char* inData, std::vector& outData) { SCOPED_TIMER("AI"); - if (id_skirmishAI.empty()) { + if (hostSkirmishAIs.empty()) return false; - } unsigned int n = 0; if (aiTeam != -1) { // get the AI's for team - const team_ais_t::iterator aiTeamIter = team_skirmishAIs.find(aiTeam); + const auto aiTeamIt = teamSkirmishAIs.find(aiTeam); - if (aiTeamIter == team_skirmishAIs.end()) { + if (aiTeamIt == teamSkirmishAIs.end()) return false; - } // get the vector of ID's for the AI's - ids_t& aiIDs = aiTeamIter->second; + const ids_t& aiIDs = aiTeamIt->second; outData.resize(aiIDs.size(), ""); // send only to AI's in team - for (auto aiIDsIter = aiIDs.begin(); aiIDsIter != aiIDs.end(); ++aiIDsIter) { - CSkirmishAIWrapper* wrapperAI = id_skirmishAI[*aiIDsIter].get(); + for (uint8_t aiID: aiIDs) { + CSkirmishAIWrapper* wrapperAI = hostSkirmishAIs[aiID].get(); wrapperAI->SendLuaMessage(inData, &outData[n++]); } } else { - outData.resize(id_skirmishAI.size(), ""); + outData.resize(hostSkirmishAIs.size(), ""); // broadcast to all AI's across all teams // // since neither AI ID's nor AI teams are // necessarily consecutive, store responses // in calling order - for (auto it = id_skirmishAI.begin(); it != id_skirmishAI.end(); ++it) { - CSkirmishAIWrapper* wrapperAI = (it->second).get(); + for (auto& p: hostSkirmishAIs) { + CSkirmishAIWrapper* wrapperAI = (p.second).get(); wrapperAI->SendLuaMessage(inData, &outData[n++]); } } @@ -527,7 +533,7 @@ bool CEngineOutHandler::SendLuaMessages(int aiTeam, const char* inData, std::vec -void CEngineOutHandler::CreateSkirmishAI(const size_t skirmishAIId) { +void CEngineOutHandler::CreateSkirmishAI(const uint8_t skirmishAIId) { SCOPED_TIMER("AI"); //const bool unpauseAfterAIInit = configHandler->GetBool("AI_UnpauseAfterInit"); @@ -559,11 +565,8 @@ void CEngineOutHandler::CreateSkirmishAI(const size_t skirmishAIId) { } else { CSkirmishAIWrapper* aiWrapper = nullptr; - id_skirmishAI[skirmishAIId].reset(new CSkirmishAIWrapper(skirmishAIId)); - - aiWrapper = id_skirmishAI[skirmishAIId].get(); - - team_skirmishAIs[aiWrapper->GetTeamId()].push_back(skirmishAIId); + hostSkirmishAIs[skirmishAIId].reset(aiWrapper = new CSkirmishAIWrapper(skirmishAIId)); + teamSkirmishAIs[aiWrapper->GetTeamId()].push_back(skirmishAIId); aiWrapper->Init(); @@ -572,10 +575,9 @@ void CEngineOutHandler::CreateSkirmishAI(const size_t skirmishAIId) { if (skirmishAIHandler.IsLocalSkirmishAIDieing(skirmishAIId)) return; - if (!gs->PreSimFrame()) { - // We will only get here if the AI is created mid-game. + // We will only get here if the AI is created mid-game. + if (!gs->PreSimFrame()) aiWrapper->Update(gs->frameNum); - } // Send a UnitCreated event for each unit of the team. // This will only do something if the AI is created mid-game. @@ -590,37 +592,33 @@ void CEngineOutHandler::CreateSkirmishAI(const size_t skirmishAIId) { } } -void CEngineOutHandler::SetSkirmishAIDieing(const size_t skirmishAIId) { +void CEngineOutHandler::SetSkirmishAIDieing(const uint8_t skirmishAIId) { SCOPED_TIMER("AI"); // if exiting before start, AI's have not been loaded yet // and std::map<>::operator[] would insert a NULL instance - if (id_skirmishAI.find(skirmishAIId) == id_skirmishAI.end()) + if (hostSkirmishAIs.find(skirmishAIId) == hostSkirmishAIs.end()) return; - assert(id_skirmishAI[skirmishAIId].get() != nullptr); - id_skirmishAI[skirmishAIId]->Dieing(); + assert(hostSkirmishAIs[skirmishAIId].get() != nullptr); + hostSkirmishAIs[skirmishAIId]->Dieing(); } -static void internal_aiErase(std::vector& ais, const unsigned char skirmishAIId) { - auto it = std::find(ais.begin(), ais.end(), skirmishAIId); - - if (it != ais.end()) { - ais.erase(it); - return; - } +void CEngineOutHandler::DestroySkirmishAI(const uint8_t skirmishAIId) { + SCOPED_TIMER("AI"); - // failed to remove Skirmish AI ID - assert(false); -} + CSkirmishAIWrapper* aiWrapper = hostSkirmishAIs[skirmishAIId].get(); -void CEngineOutHandler::DestroySkirmishAI(const size_t skirmishAIId) { - SCOPED_TIMER("AI"); + const int teamID = aiWrapper->GetTeamId(); + const auto aiIter = std::find(teamSkirmishAIs[teamID].begin(), teamSkirmishAIs[teamID].end(), skirmishAIId); - CSkirmishAIWrapper* aiWrapper = id_skirmishAI[skirmishAIId].get(); + if (aiIter != teamSkirmishAIs[teamID].end()) { + teamSkirmishAIs[teamID].erase(aiIter); + } else { + assert(false); + } - internal_aiErase(team_skirmishAIs[aiWrapper->GetTeamId()], skirmishAIId); - id_skirmishAI.erase(skirmishAIId); + hostSkirmishAIs.erase(skirmishAIId); clientNet->Send(CBaseNetProtocol::Get().SendAIStateChanged(gu->myPlayerNum, skirmishAIId, SKIRMAISTATE_DEAD)); } diff --git a/rts/ExternalAI/EngineOutHandler.h b/rts/ExternalAI/EngineOutHandler.h index 2a841bd7357..46f1c0ccb54 100644 --- a/rts/ExternalAI/EngineOutHandler.h +++ b/rts/ExternalAI/EngineOutHandler.h @@ -74,7 +74,7 @@ class CEngineOutHandler { // Skirmish AI stuff - void CreateSkirmishAI(const size_t skirmishAIId); + void CreateSkirmishAI(const uint8_t skirmishAIId); /** * Sets a local Skirmish AI dieing. * Do not call this if you want to kill a local AI, but use @@ -83,7 +83,7 @@ class CEngineOutHandler { * @see CSkirmishAIHandler::SetLocalSkirmishAIDieing() * @see DestroySkirmishAI() */ - void SetSkirmishAIDieing(const size_t skirmishAIId); + void SetSkirmishAIDieing(const uint8_t skirmishAIId); /** * Destructs a local Skirmish AI for real. * Do not call this if you want to kill a local AI, but use @@ -92,10 +92,10 @@ class CEngineOutHandler { * @see SetSkirmishAIDieing() * @see CSkirmishAIHandler::SetLocalSkirmishAIDieing() */ - void DestroySkirmishAI(const size_t skirmishAIId); + void DestroySkirmishAI(const uint8_t skirmishAIId); - void Load(std::istream* s, const size_t skirmishAIId); - void Save(std::ostream* s, const size_t skirmishAIId); + void Load(std::istream* s, const uint8_t skirmishAIId); + void Save(std::ostream* s, const uint8_t skirmishAIId); private: typedef std::vector ids_t; @@ -103,13 +103,13 @@ class CEngineOutHandler { typedef std::map team_ais_t; /// Contains all local Skirmish AIs, indexed by their ID - id_ai_t id_skirmishAI; + id_ai_t hostSkirmishAIs; /** * Array mapping team IDs to local Skirmish AI instances. * There can be multiple Skirmish AIs per team. */ - team_ais_t team_skirmishAIs; + team_ais_t teamSkirmishAIs; }; #define eoh CEngineOutHandler::GetInstance() diff --git a/rts/System/LoadSave/CregLoadSaveHandler.cpp b/rts/System/LoadSave/CregLoadSaveHandler.cpp index ad0b02dc536..8d69a2ff08e 100644 --- a/rts/System/LoadSave/CregLoadSaveHandler.cpp +++ b/rts/System/LoadSave/CregLoadSaveHandler.cpp @@ -30,7 +30,7 @@ #include "Sim/Units/Scripts/UnitScriptEngine.h" #include "Sim/Units/Scripts/NullUnitScript.h" #include "Game/UI/Groups/GroupHandler.h" - +#include "System/SafeUtil.h" #include "System/Platform/errorhandler.h" #include "System/FileSystem/DataDirsAccess.h" #include "System/FileSystem/FileQueryFlags.h" @@ -40,6 +40,7 @@ #include "System/Log/ILog.h" + CCregLoadSaveHandler::CCregLoadSaveHandler() : iss(nullptr) {} @@ -125,8 +126,8 @@ void CCregLoadSaveHandler::SaveGame(const std::string& path) { #ifdef USING_CREG LOG("Saving game"); - try { + try { std::stringstream oss; // write our own header. SavePackage() will add its own @@ -137,20 +138,27 @@ void CCregLoadSaveHandler::SaveGame(const std::string& path) CGameStateCollector gsc = CGameStateCollector(); - // save creg state - creg::COutputStreamSerializer os; - os.SavePackage(&oss, &gsc, gsc.GetClass()); - PrintSize("Game", oss.tellp()); - - // save ai state - int aistart = oss.tellp(); - const CSkirmishAIHandler::id_ai_t& ais = skirmishAIHandler.GetAllSkirmishAIs(); - for (const auto& ai : ais) { - std::stringstream aidata; - eoh->Save(&aidata, ai.first); - oss << (std::streamsize)aidata.tellp() << aidata.rdbuf(); + { + // save creg state + creg::COutputStreamSerializer os; + os.SavePackage(&oss, &gsc, gsc.GetClass()); + PrintSize("Game", oss.tellp()); + } + { + // save AI state + const int aiStart = oss.tellp(); + + // reset by each Save() call + std::stringstream aiData; + + for (const auto& ai: skirmishAIHandler.GetAllSkirmishAIs()) { + eoh->Save(&aiData, ai.first); + + oss << (std::streamsize) aiData.tellp(); + oss << aiData.rdbuf(); + } + PrintSize("AIs", ((int)oss.tellp()) - aiStart); } - PrintSize("AIs", ((int)oss.tellp()) - aistart); gzFile file = gzopen(dataDirsAccess.LocateFile(path, FileQueryFlags::WRITE).c_str(), "wb9"); if (file == nullptr) { @@ -227,41 +235,34 @@ void CCregLoadSaveHandler::LoadGame() #ifdef USING_CREG ENTER_SYNCED_CODE(); - void* pGSC = NULL; - creg::Class* gsccls = NULL; + void* pGSC = nullptr; + creg::Class* gsccls = nullptr; // load creg state creg::CInputStreamSerializer inputStream; inputStream.LoadPackage(iss, pGSC, gsccls); assert(pGSC && gsccls == CGameStateCollector::StaticClass()); + // the only job of gsc is to collect gamestate data CGameStateCollector* gsc = static_cast(pGSC); - delete gsc; // the only job of gsc is to collect gamestate data - gsc = NULL; + spring::SafeDelete(gsc); // load ai state - const CSkirmishAIHandler::id_ai_t& ais = skirmishAIHandler.GetAllSkirmishAIs(); - for (const auto& ai : ais) { - std::streamsize aisize; - *iss >> aisize; - std::vector buffer(aisize); + for (const auto& ai: skirmishAIHandler.GetAllSkirmishAIs()) { + std::streamsize aiSize; + *iss >> aiSize; + std::vector buffer(aiSize); iss->read(&buffer[0], buffer.size()); - std::stringstream aidata; - aidata.write(&buffer[0], buffer.size()); - eoh->Load(&aidata, ai.first); + std::stringstream aiData; + aiData.write(&buffer[0], buffer.size()); + eoh->Load(&aiData, ai.first); } - //for (int a=0; a < teamHandler->ActiveTeams(); a++) { // For old savegames - // if (teamHandler->Team(a)->isDead && eoh->IsSkirmishAI(a)) { - // eoh->DestroySkirmishAI(skirmishAIId(a), 2 /* = team died */); - // } - //} // cleanup - delete iss; - iss = NULL; + spring::SafeDelete(iss); gs->paused = false; - if (gameServer) { + if (gameServer != nullptr) { gameServer->isPaused = false; gameServer->syncErrorFrame = 0; } diff --git a/rts/System/LoadSave/LuaLoadSaveHandler.cpp b/rts/System/LoadSave/LuaLoadSaveHandler.cpp index f2b01961a3e..eea19fb06c5 100644 --- a/rts/System/LoadSave/LuaLoadSaveHandler.cpp +++ b/rts/System/LoadSave/LuaLoadSaveHandler.cpp @@ -23,6 +23,7 @@ #include "System/Exceptions.h" #include "System/Log/ILog.h" #include "System/Util.h" +#include "System/SafeUtil.h" @@ -120,12 +121,16 @@ void CLuaLoadSaveHandler::SaveGameStartInfo() void CLuaLoadSaveHandler::SaveAIData() { - const CSkirmishAIHandler::id_ai_t& ais = skirmishAIHandler.GetAllSkirmishAIs(); - for (const auto& ai : ais) { - std::stringstream aidata; - eoh->Save(&aidata, ai.first); - std::string aisection = FILE_AIDATA + IntToString(ai.first, ".%i"); - SaveEntireFile(aisection.c_str(), "AI data", aidata.str().data(), aidata.tellp()); + // reset by each Save() call + std::stringstream aiData; + + for (const auto& ai: skirmishAIHandler.GetAllSkirmishAIs()) { + eoh->Save(&aiData, ai.first); + + const std::string aiSection = FILE_AIDATA + IntToString(ai.first, ".%i"); + const std::string aiDataStr = aiData.str(); + + SaveEntireFile(aiSection.c_str(), "AI data", aiDataStr.data(), aiData.tellp()); } } @@ -209,11 +214,13 @@ void CLuaLoadSaveHandler::LoadEventClients() void CLuaLoadSaveHandler::LoadAIData() { - const CSkirmishAIHandler::id_ai_t& ais = skirmishAIHandler.GetAllSkirmishAIs(); - for (const auto& ai : ais) { - std::string aisection = FILE_AIDATA + IntToString(ai.first, ".%i"); - std::stringstream aidata(LoadEntireFile(aisection)); - eoh->Load(&aidata, ai.first); + for (const auto& ai: skirmishAIHandler.GetAllSkirmishAIs()) { + const std::string aiSection = FILE_AIDATA + IntToString(ai.first, ".%i"); + const std::string aiDataFile = LoadEntireFile(aiSection); + + std::stringstream aiData(aiDataFile); + + eoh->Load(&aiData, ai.first); } }