Skip to content

Commit

Permalink
Rework MakeDirList() method and add more flags to it.
Browse files Browse the repository at this point in the history
  • Loading branch information
DreamyCecil committed Jul 31, 2024
1 parent ee4c7cd commit 7c82d8f
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 65 deletions.
167 changes: 105 additions & 62 deletions Sources/Engine/Base/Directory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,84 +90,127 @@ void FillDirList_internal(CTFileName fnmBasePath,
}
}

// [Cecil] Moved code out of MakeDirList()
static void ListFromGRO(CDynamicStackArray<CTFileName> &afnmTemp, const CTFileName &fnmDir, const CTString &strPattern, ULONG ulFlags) {
// [Cecil] Ignore packages
if (ulFlags & DLI_IGNOREGRO) return;

const BOOL bMod = (_fnmMod != "");
const BOOL bRecursive = (ulFlags & DLI_RECURSIVE);
const BOOL bLists = bMod && !(ulFlags & DLI_IGNORELISTS);

const INDEX ctFilesInZips = UNZIPGetFileCount();

for (INDEX iFileInZip = 0; iFileInZip < ctFilesInZips; iFileInZip++) {
// Get ZIP entry
const CZipEntry &ze = UNZIPGetEntry(iFileInZip);
const CTFileName &fnm = ze.ze_fnm;

// Skip if not under this directory
if (bRecursive) {
if (!fnm.HasPrefix(fnmDir)) continue;

// Skip if not the same directory
} else if (fnm.FileDir() != fnmDir) {
continue;
}

// Doesn't match the pattern
if (strPattern != "" && !fnm.Matches(strPattern)) continue;

const BOOL bFileFromMod = UNZIPIsFileAtIndexMod(iFileInZip);

// List files exclusively from the mod
if (ulFlags & DLI_ONLYMOD) {
if (bMod && bFileFromMod) {
afnmTemp.Push() = fnm;
}

// List files from the game
} else if (!bFileFromMod) {
// Not a mod file or shouldn't match mod's browse paths
if (!bLists) {
afnmTemp.Push() = fnm;

// Matches mod's browse paths
} else if (FileMatchesList(_afnmBaseBrowseInc, fnm) && FileMatchesList(_afnmBaseBrowseExc, fnm)) {
afnmTemp.Push() = fnm;
}

// List extras from the mod
} else if (!(ulFlags & DLI_IGNOREMOD) && bMod) {
afnmTemp.Push() = fnm;
}
}
};

// make a list of all files in a directory
ENGINE_API void MakeDirList(
CDynamicStackArray<CTFileName> &afnmDir, const CTFileName &fnmDir, const CTString &strPattern, ULONG ulFlags)
{
afnmDir.PopAll();
BOOL bRecursive = ulFlags&DLI_RECURSIVE;
BOOL bSearchCD = ulFlags&DLI_SEARCHCD;

// make one temporary array
CDynamicStackArray<CTFileName> afnm;

if (_fnmMod!="") {
FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, strPattern, bRecursive,
&_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
if (bSearchCD) {
FillDirList_internal(_fnmCDPath, afnm, fnmDir, strPattern, bRecursive,
&_afnmBaseBrowseInc, &_afnmBaseBrowseExc);
}
FillDirList_internal(_fnmApplicationPath+_fnmMod, afnm, fnmDir, strPattern, bRecursive, NULL, NULL);
} else {
FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, strPattern, bRecursive, NULL, NULL);
if (bSearchCD) {
FillDirList_internal(_fnmCDPath, afnm, fnmDir, strPattern, bRecursive, NULL, NULL);
}
// Make a temporary list
CDynamicStackArray<CTFileName> afnmTemp;

// [Cecil] Reuse the file list
if (ulFlags & DLI_REUSELIST) {
afnmTemp = afnmDir;
}

// for each file in zip archives
CTString strDirPattern = fnmDir;
INDEX ctFilesInZips = UNZIPGetFileCount();
for(INDEX iFileInZip=0; iFileInZip<ctFilesInZips; iFileInZip++) {
const CTFileName &fnm = UNZIPGetFileAtIndex(iFileInZip);
// Clear the final list
afnmDir.PopAll();

// if not in this dir, skip it
if (bRecursive) {
if (!fnm.HasPrefix(strDirPattern)) {
continue;
}
} else {
if (fnm.FileDir()!=fnmDir) {
continue;
}
}
const BOOL bMod = (_fnmMod != "");
const BOOL bRecursive = (ulFlags & DLI_RECURSIVE);

// Skip if doesn't match the pattern
if (strPattern != "" && !FileSystem::PathMatches(fnm, strPattern)) {
continue;
// [Cecil] Determine whether browse lists from a mod should be used
const BOOL bLists = bMod && !(ulFlags & DLI_IGNORELISTS);
CDynamicStackArray<CTString> *paBaseBrowseInc = (bLists ? &_afnmBaseBrowseInc : NULL);
CDynamicStackArray<CTString> *paBaseBrowseExc = (bLists ? &_afnmBaseBrowseExc : NULL);

// [Cecil] List files exclusively from GRO packages (done afterwards)
if (ulFlags & DLI_ONLYGRO) {
NOTHING;

// [Cecil] List files exclusively from the mod
} else if (ulFlags & DLI_ONLYMOD) {
if (bMod) {
FillDirList_internal(_fnmApplicationPath + _fnmMod, afnmTemp, fnmDir, strPattern, bRecursive, NULL, NULL);
}

// if mod is active, and the file is not in mod
if (_fnmMod!="" && !UNZIPIsFileAtIndexMod(iFileInZip)) {
// if it doesn't match base browse path
if ( !FileMatchesList(_afnmBaseBrowseInc, fnm) || FileMatchesList(_afnmBaseBrowseExc, fnm) ) {
// skip it
continue;
}
} else {
// List files from the game directory
FillDirList_internal(_fnmApplicationPath, afnmTemp, fnmDir, strPattern, bRecursive, paBaseBrowseInc, paBaseBrowseExc);

// List extra files from the CD
if (ulFlags & DLI_SEARCHCD && _fnmCDPath != "") {
FillDirList_internal(_fnmCDPath, afnmTemp, fnmDir, strPattern, bRecursive, paBaseBrowseInc, paBaseBrowseExc);
}

// add that file
afnm.Push() = fnm;
// List extra files from the mod directory
if (!(ulFlags & DLI_IGNOREMOD) && bMod) {
FillDirList_internal(_fnmApplicationPath + _fnmMod, afnmTemp, fnmDir, strPattern, bRecursive, NULL, NULL);
}
}

// if no files
if (afnm.Count()==0) {
// don't check for duplicates
return;
}
// [Cecil] Search for files in the packages
ListFromGRO(afnmTemp, fnmDir, strPattern, ulFlags);

const INDEX ctFiles = afnmTemp.Count();

// Don't check for duplicates if no files
if (ctFiles == 0) return;

// resort the array
qsort(afnm.da_Pointers, afnm.Count(), sizeof(void*), qsort_CompareCTFileName);
// Sort the file list
qsort(afnmTemp.da_Pointers, afnmTemp.Count(), sizeof(CTFileName *), qsort_CompareCTFileName);

// for each file
INDEX ctFiles = afnm.Count();
for (INDEX iFile=0; iFile<ctFiles; iFile++) {
// if not same as last one
if (iFile==0 || afnm[iFile]!=afnm[iFile-1]) {
// copy over to final array
afnmDir.Push() = afnm[iFile];
// Copy the first file into the final list
afnmDir.Push() = afnmTemp[0];

// Copy the rest of the files if they aren't matching previous files
for (INDEX iFile = 1; iFile < ctFiles; iFile++)
{
if (afnmTemp[iFile] != afnmTemp[iFile - 1]) {
afnmDir.Push() = afnmTemp[iFile];
}
}
}
};
18 changes: 15 additions & 3 deletions Sources/Engine/Base/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,21 @@ ENGINE_API BOOL RemoveFile(const CTFileName &fnmFile);
#define EFP_MODZIP 3 // file in one of mod zips
ENGINE_API INDEX ExpandFilePath(ULONG ulType, const CTFileName &fnmFile, CTFileName &fnmExpanded);

// these are input flags for directory reading
#define DLI_RECURSIVE (1UL<<0) // recurse into subdirs
#define DLI_SEARCHCD (1UL<<1) // search the CD path also
// [Cecil] New flags for listing files in some directory using MakeDirList()
enum EDirListFlags {
// Old generic flags
DLI_RECURSIVE = (1 << 0), // Look into subdirectories
DLI_SEARCHCD = (1 << 1), // List extra files from the CD

// New flags
DLI_REUSELIST = (1 << 2), // Reuse existing entries in the provided list
DLI_ONLYMOD = (1 << 3), // List files exclusively from the mod directory
DLI_ONLYGRO = (1 << 4), // List files exclusively from GRO packages
DLI_IGNOREMOD = (1 << 5), // Ignore extra files from the mod
DLI_IGNORELISTS = (1 << 6), // Ignore include/exclude lists, if playing a mod
DLI_IGNOREGRO = (1 << 7), // Ignore files from GRO packages
};

// make a list of all files in a directory
ENGINE_API void MakeDirList(
CDynamicStackArray<CTFileName> &adeDir,
Expand Down

0 comments on commit 7c82d8f

Please sign in to comment.