Fix sync loss and missing landscape or objects when joining two consecutive games without restarting the engine inbetween

Caused by an outdated cache of the DirectoryIterator in the main scenario group
stable-5.3
Sven Eberhardt 2012-11-17 19:44:04 +01:00
parent 4a3a6e5260
commit ed971eba46
4 changed files with 27 additions and 8 deletions

View File

@ -501,7 +501,7 @@ void C4Group::Init()
SearchPtr=NULL;
// Folder only
//hFdt=-1;
FolderSearch.Reset();
FolderSearch.Clear();
// Error status
SCopy("No Error",ErrorString,C4GroupMaxError);
}
@ -1041,13 +1041,13 @@ bool C4Group::AppendEntry2StdFile(C4GroupEntry *centry, CStdFile &hTarget)
return true;
}
void C4Group::ResetSearch()
void C4Group::ResetSearch(bool reload_contents)
{
switch (Status)
{
case GRPF_Folder:
SearchPtr=NULL;
FolderSearch.Reset(FileName);
FolderSearch.Reset(FileName, reload_contents);
if (*FolderSearch)
{
FolderSearchEntry.Set(FolderSearch,FileName);
@ -1465,6 +1465,8 @@ bool C4Group::DeleteEntry(const char *szFilename, bool fRecycle)
if (!EraseItem(szPath)) return false;
}
break;
// refresh file list
ResetSearch(true);
}
return true;
}
@ -1493,6 +1495,8 @@ bool C4Group::Rename(const char *szFile, const char *szNewName)
char path2[_MAX_FNAME+1]; SCopy(FileName,path2,_MAX_PATH-1);
AppendBackslash(path2); SAppend(szNewName,path2,_MAX_PATH);
if (!RenameFile(path,path2)) return Error("Rename: Failure");
// refresh file list
ResetSearch(true);
break;
}

View File

@ -242,7 +242,7 @@ public:
bool Read(void *pBuffer, size_t iSize);
bool Advance(int iOffset);
void SetStdOutput(bool fStatus);
void ResetSearch();
void ResetSearch(bool reload_contents=false); // reset search pointer so calls to FindNextEntry find first entry again. if reload_contents is set, the file list for directories is also refreshed.
const char *GetError();
const char *GetName();
StdStrBuf GetFullName() const;

View File

@ -932,14 +932,28 @@ DirectoryIterator::~DirectoryIterator()
delete p;
}
void DirectoryIterator::Clear()
{
// clear cache
if (p->ref > 1)
{
// Detach from shared memory
--p->ref;
p = new DirectoryIteratorP;
}
p->directory.clear();
p->files.clear();
iter = p->files.end();
}
void DirectoryIterator::Reset ()
{
iter = p->files.begin();
}
void DirectoryIterator::Reset (const char * dirname)
void DirectoryIterator::Reset (const char * dirname, bool force_reread)
{
if (p->directory == dirname)
if (p->directory == dirname && !force_reread)
{
// Skip reinitialisation and just reset the iterator
iter = p->files.begin();

View File

@ -103,8 +103,9 @@ public:
const char * operator * () const;
DirectoryIterator& operator ++ ();
DirectoryIterator operator ++ (int);
void Reset(const char * dirname);
void Reset();
void Clear(); // put iterator into empty state and clear any cached directory listing
void Reset(const char * dirname, bool force_reread=false); // reset iterator to front of file list. re-read directory if it changed or force_reread is set.
void Reset(); // reset iterator to front of file list without re-reading directory
private:
void Read(const char *dirname);
friend struct DirectoryIteratorP;