List the Custom Edition map folders through a handle of their own

custom_edition_maps_look_for listed custom_maps and the install's maps
folder with find_files_start and find_files_next, which keep their place
in one global (find_files_globals). As the game starts, the menus' thread
for the file system's checks (filesystem_initialization_thread_proc in
ui_widget.c) makes the default gametypes' folders with
directory_create_or_delete_contents, which deletes a folder's files with
the same two functions. A map list looked for meanwhile takes that
listing's place, and the thread then deletes the files of the folder being
listed: the player's Custom Edition maps.

The menus take no input until that thread is done, so it takes a start
that asks for the maps at once. Seen with debug.menu_open set to the
Select Map screen
(main_menu/multiplayer_type_select/mp_map_select/mp_map_select_screen) on
a Windows build of c9e4f13f, with six files in custom_maps: one was left.

Each folder is now listed with FindFirstFileA and FindNextFileA on a
handle of the function's own. The same start, twice, left the six files
and listed the three maps among them. Not run on Linux or Android.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jonas VolmanandClaude Opus 5.5 committed 2026-10-10 01:37:01 -07:00
1 parent c9e4f13fdb
commit a845bbf55d
1 file changed
+33 -11
+33 -11
View File
@@ -44,6 +44,8 @@ Each map can have, beside it in its folder:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xtl.h>
/* ---------- constants */
@@ -388,10 +390,6 @@ static void custom_edition_maps_look_for(
void)
{
struct custom_edition_maps_globals *globals = &custom_edition_maps_globals;
struct file_reference directory;
struct file_reference file;
char name[MAXIMUM_FILENAME_LENGTH + 1];
char extension[MAXIMUM_FILENAME_LENGTH + 1];
char const *folders[] = { CUSTOM_EDITION_MAP_DIRECTORY, CUSTOM_EDITION_INSTALL_MAP_DIRECTORY };
short folder_index;
@@ -405,17 +403,41 @@ static void custom_edition_maps_look_for(
/* the game's custom_maps first, so its copy wins */
for (folder_index = 0; folder_index < NUMBEROF(folders); folder_index++)
{
char pattern[MAXIMUM_FILENAME_LENGTH + 1];
WIN32_FIND_DATAA data;
HANDLE find;
/* (the install's only when there is one) */
if (folder_index && !custom_edition_install_present())
continue;
file_reference_create_from_path(&directory, folders[folder_index], TRUE);
find_files_start(0, &directory);
while (find_files_next(&file, NULL))
/* A folder is listed through a handle of its own, never with
find_files_start and find_files_next: those keep their place in one
global, and as the game starts a thread of the menus' deletes the
files of folders with them (perform_filesystem_initialization in
ui_widget.c, directory_create_or_delete_contents). A listing here at
the same time takes that one's place, and the thread then deletes
the files of this folder: the maps. */
csprintf(pattern, "%s*.*", folders[folder_index]);
find = FindFirstFileA(pattern, &data);
if (find == INVALID_HANDLE_VALUE)
continue;
do
{
file_reference_get_name(&file, FLAG(_name_filename_bit), name);
file_reference_get_name(&file, FLAG(_name_extension_bit), extension);
custom_edition_map_add(folders[folder_index], name, extension);
}
char name[sizeof(data.cFileName) + 1];
char *extension;
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
csmemcpy(name, data.cFileName, sizeof(data.cFileName));
name[sizeof(data.cFileName)] = 0;
extension = strrchr(name, '.');
if (extension)
{
*extension++ = 0;
custom_edition_map_add(folders[folder_index], name, extension);
}
} while (FindNextFileA(find, &data));
CloseHandle(find);
}
qsort(globals->maps, globals->map_count, sizeof(globals->maps[0]), custom_edition_map_compare);
qsort(globals->campaigns, globals->campaign_count, sizeof(globals->campaigns[0]), custom_edition_map_compare);