From 4182be321695306385543c0584cb780959ceb25e Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sun, 16 Aug 2015 15:25:46 +0200 Subject: [PATCH] Never save copy of programs from level files when saving scene Prevents some possible bugs related to changing level files. This might also slightly improve saving time (which is kinda important with one-threaded autosaves ;)) --- src/level/robotmain.cpp | 1 - .../implementation/program_storage_impl.cpp | 55 +++++++++++++++---- src/object/interface/program_storage_object.h | 2 +- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 46655a0a..bf51167f 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -4301,7 +4301,6 @@ void CRobotMain::SaveAllScript() } //! Saves all programs of the robot. -//! If a program does not exist, the corresponding file is destroyed. void CRobotMain::SaveOneScript(CObject *obj) { if (! obj->Implements(ObjectInterfaceType::ProgramStorage)) return; diff --git a/src/object/implementation/program_storage_impl.cpp b/src/object/implementation/program_storage_impl.cpp index bb444339..3c705bd9 100644 --- a/src/object/implementation/program_storage_impl.cpp +++ b/src/object/implementation/program_storage_impl.cpp @@ -75,6 +75,7 @@ bool CProgramStorageObjectImpl::IntroduceVirus() int programIndex = rand() % m_program.size(); if ( m_program[programIndex]->script->IntroduceVirus() ) // tries to introduce { + m_program[programIndex]->filename = ""; // The program is changed, so force it to save instead of just the filename m_activeVirus = true; // active virus return true; } @@ -108,8 +109,6 @@ Program* CProgramStorageObjectImpl::AddProgram() assert(m_object->Implements(ObjectInterfaceType::Old)); //TODO auto program = MakeUnique(); program->script = MakeUnique(dynamic_cast(this)); - program->readOnly = false; - program->runnable = true; Program* prog = program.get(); AddProgram(std::move(program)); @@ -246,7 +245,7 @@ void CProgramStorageObjectImpl::SaveAllUserPrograms(const std::string& userSourc { std::string filename = userSource + StrUtils::Format("%.3d%.3d.txt", m_programStorageIndex, i); - if (i < m_program.size() && !m_program[i]->loadedFromLevel) + if (i < m_program.size() && m_program[i]->filename.empty()) { GetLogger()->Trace("Saving program '%s' into user directory\n", filename.c_str()); WriteProgram(m_program[i].get(), filename); @@ -275,7 +274,7 @@ void CProgramStorageObjectImpl::LoadAllProgramsForLevel(CLevelParserLine* levelS ReadProgram(program, filename); program->readOnly = levelSource->GetParam(opReadOnly)->AsBool(true); program->runnable = levelSource->GetParam(opRunnable)->AsBool(true); - program->loadedFromLevel = true; + program->filename = levelSource->GetParam(op)->AsString(); if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run) { @@ -296,7 +295,7 @@ void CProgramStorageObjectImpl::LoadAllProgramsForLevel(CLevelParserLine* levelS ReadProgram(program, filename); program->readOnly = true; program->runnable = false; - program->loadedFromLevel = true; + program->filename = levelSource->GetParam("soluce")->AsString(); } if (m_programStorageIndex >= 0) @@ -319,7 +318,19 @@ void CProgramStorageObjectImpl::LoadAllProgramsForLevel(CLevelParserLine* levelS void CProgramStorageObjectImpl::SaveAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource) { levelSourceLine->AddParam("programStorageIndex", MakeUnique(m_programStorageIndex)); - assert(m_programStorageIndex != -1); + + for (unsigned int i = 0; i < m_program.size(); i++) + { + if (!m_program[i]->filename.empty() && m_program[i]->readOnly) + { + levelSourceLine->AddParam("script" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->filename)); + levelSourceLine->AddParam("scriptReadOnly" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->readOnly)); + levelSourceLine->AddParam("scriptRunnable" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->runnable)); + } + } + + if (m_programStorageIndex < 0) return; + if (!m_object->Implements(ObjectInterfaceType::Controllable) || !dynamic_cast(m_object)->GetSelectable() || m_object->GetType() == OBJECT_HUMAN) return; GetLogger()->Debug("Saving saved scene programs to '%s/prog%.3d___.txt'\n", levelSource.c_str(), m_programStorageIndex); for (int i = 0; i < 999; i++) @@ -330,21 +341,45 @@ void CProgramStorageObjectImpl::SaveAllProgramsForSavedScene(CLevelParserLine* l CResourceManager::Remove(filename); continue; } + if (!m_program[i]->filename.empty() && m_program[i]->readOnly) continue; - levelSourceLine->AddParam("scriptReadOnly" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->readOnly)); - levelSourceLine->AddParam("scriptRunnable" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->runnable)); GetLogger()->Trace("Saving program '%s' to saved scene\n", filename.c_str()); WriteProgram(m_program[i].get(), filename); + levelSourceLine->AddParam("scriptReadOnly" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->readOnly)); + levelSourceLine->AddParam("scriptRunnable" + StrUtils::ToString(i+1), MakeUnique(m_program[i]->runnable)); } } void CProgramStorageObjectImpl::LoadAllProgramsForSavedScene(CLevelParserLine* levelSourceLine, const std::string& levelSource) { + int run = levelSourceLine->GetParam("run")->AsInt(0)-1; m_programStorageIndex = levelSourceLine->GetParam("programStorageIndex")->AsInt(-1); - if(m_programStorageIndex == -1) return; + + for (int i = 0; i <= 999; i++) + { + std::string op = "script" + StrUtils::ToString(i+1); // script1..script10 + std::string opReadOnly = "scriptReadOnly" + StrUtils::ToString(i+1); // scriptReadOnly1..scriptReadOnly10 + std::string opRunnable = "scriptRunnable" + StrUtils::ToString(i+1); // scriptRunnable1..scriptRunnable10 + if (levelSourceLine->GetParam(op)->IsDefined()) + { + std::string filename = levelSourceLine->GetParam(op)->AsPath("ai"); + GetLogger()->Trace("Loading program '%s' from saved scene\n", filename.c_str()); + Program* program = GetOrAddProgram(i); + ReadProgram(program, filename); + program->readOnly = levelSourceLine->GetParam(opReadOnly)->AsBool(true); + program->runnable = levelSourceLine->GetParam(opRunnable)->AsBool(true); + program->filename = levelSourceLine->GetParam(op)->AsString(); + + if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run) + { + dynamic_cast(m_object)->RunProgram(program); + } + } + } + + if(m_programStorageIndex < 0) return; GetLogger()->Debug("Loading saved scene programs from '%s/prog%.3d___.txt'\n", levelSource.c_str(), m_programStorageIndex); - int run = levelSourceLine->GetParam("run")->AsInt(0)-1; for (int i = 0; i <= 999; i++) { std::string opReadOnly = "scriptReadOnly" + StrUtils::ToString(i+1); // scriptReadOnly1..scriptReadOnly10 diff --git a/src/object/interface/program_storage_object.h b/src/object/interface/program_storage_object.h index 3b595b29..c89bc053 100644 --- a/src/object/interface/program_storage_object.h +++ b/src/object/interface/program_storage_object.h @@ -33,7 +33,7 @@ struct Program std::unique_ptr script; bool readOnly = false; bool runnable = true; - bool loadedFromLevel = false; + std::string filename; }; /**