4949#include " Common/ArchiveFile.h"
5050#include " Common/ArchiveFileSystem.h"
5151#include " Common/AsciiString.h"
52+ #include " Common/LocalFileSystem.h"
5253#include " Common/PerfTimer.h"
5354#include " ../NGMP_include.h"
5455#include " ../OnlineServices_Init.h"
@@ -94,6 +95,15 @@ ArchiveFileSystem *TheArchiveFileSystem = nullptr;
9495// Private Functions
9596// ----------------------------------------------------------------------------
9697
98+ static AsciiString getBaseFilename (const AsciiString& path)
99+ {
100+ const char * str = path.str ();
101+ const char * p1 = strrchr (str, ' \\ ' );
102+ const char * p2 = strrchr (str, ' /' );
103+ const char * sep = (p1 == nullptr ) ? p2 : ((p2 == nullptr ) ? p1 : ((p1 > p2) ? p1 : p2));
104+ return sep ? AsciiString (sep + 1 ) : path;
105+ }
106+
97107
98108
99109// ----------------------------------------------------------------------------
@@ -117,7 +127,7 @@ ArchiveFileSystem::~ArchiveFileSystem()
117127 }
118128}
119129
120- void ArchiveFileSystem::loadIntoDirectoryTree (ArchiveFile *archiveFile, Bool overwrite)
130+ void ArchiveFileSystem::loadIntoDirectoryTree (ArchiveFile *archiveFile, Bool overwrite, Bool sortedByName )
121131{
122132
123133 FilenameList filenameList;
@@ -157,7 +167,16 @@ void ArchiveFileSystem::loadIntoDirectoryTree(ArchiveFile *archiveFile, Bool ove
157167 }
158168
159169 ArchivedFileLocationMap::iterator fileIt;
160- if (overwrite)
170+ if (sortedByName)
171+ {
172+ // Insert by case-insensitive archive filename, matching game folder load order where the alphabetically first archive wins.
173+ const AsciiString baseName = getBaseFilename (archiveFile->getName ());
174+ std::pair<ArchivedFileLocationMap::iterator, ArchivedFileLocationMap::iterator> range = dirInfo->m_files .equal_range (token);
175+ fileIt = range.first ;
176+ while (fileIt != range.second && getBaseFilename (fileIt->second ->getName ()).compareNoCase (baseName) <= 0 )
177+ ++fileIt;
178+ }
179+ else if (overwrite)
161180 {
162181 // When overwriting, try place the new value at the beginning of the key list.
163182 fileIt = dirInfo->m_files .find (token);
@@ -218,9 +237,20 @@ void ArchiveFileSystem::loadMods()
218237 // load community data patch BIG
219238 if (NGMP_OnlineServicesManager::Settings.DataPacks_UseCommunityPatch ())
220239 {
221- std::string strSettingsFileDir = std::format (" {}/GeneralsOnlineGameData/" , TheGlobalData->getPath_UserData ().str ());
222- bool bLoaded = TheArchiveFileSystem->loadBigFilesFromDirectory (strSettingsFileDir.c_str (), " 500_900_CommunityPatch_CoreINI.big" , TRUE );
223- NetworkLog (ELogVerbosity::LOG_RELEASE , " Loaded community patch: %d" , bLoaded);
240+ std::string strBigPath = std::format (" {}GeneralsOnlineGameData/500_900_CommunityPatch_CoreINI.big" , TheGlobalData->getPath_UserData ().str ());
241+ bool bLoaded = false ;
242+ if (TheLocalFileSystem->doesFileExist (strBigPath.c_str ()))
243+ {
244+ ArchiveFile* archiveFile = openArchiveFile (strBigPath.c_str ());
245+ if (archiveFile != nullptr )
246+ {
247+ // Sorted by filename so the patch respects the addon number order of BIGs in the game folder.
248+ loadIntoDirectoryTree (archiveFile, FALSE , TRUE );
249+ m_archiveFileMap[AsciiString (strBigPath.c_str ())] = archiveFile;
250+ bLoaded = true ;
251+ }
252+ }
253+ NetworkLog (ELogVerbosity::LOG_RELEASE , " Loaded community patch (%s): %d" , strBigPath.c_str (), bLoaded);
224254 }
225255#endif
226256
0 commit comments