diff --git a/tools/installer/ChooseMethod.cpp b/tools/installer/ChooseMethod.cpp index 11199793..a3790f52 100644 --- a/tools/installer/ChooseMethod.cpp +++ b/tools/installer/ChooseMethod.cpp @@ -5,6 +5,7 @@ #include "GamesList.h" #include "SelectGame.h" +game_group_t *g_game_group = NULL; unsigned int method_chosen = 0; TCHAR method_path[MAX_PATH]; @@ -160,12 +161,32 @@ INT_PTR CALLBACK ChooseMethodHandler(HWND hDlg, UINT message, WPARAM wParam, LPA if (game_type != 0) { - int reason; + g_game_group = NULL; - if ((reason = FindGames(game_type)) < 1) + BuildGameDB(); + + if (game_type == GAMES_DEDICATED) { - DisplayBadGamesDialog(hDlg, game_type, reason); - break; + g_game_group = &g_games.dedicated; + } + else if (game_type == GAMES_LISTEN) + { + g_game_group = &g_games.listen; + } + else if (game_type == GAMES_STANDALONE) + { + g_game_group = &g_games.standalone; + } + + if (g_game_group == NULL) + { + return (INT_PTR)TRUE; + } + + if (g_game_group->list_count == 0) + { + DisplayBadGamesDialog(hDlg, g_game_group->error_code); + return (INT_PTR)TRUE; } /* If we got a valid games list, we can display the next diff --git a/tools/installer/ChooseMethod.h b/tools/installer/ChooseMethod.h index 21459a8f..4b1f2b21 100644 --- a/tools/installer/ChooseMethod.h +++ b/tools/installer/ChooseMethod.h @@ -2,7 +2,10 @@ #define _INCLUDE_INSTALLER_CHOOSE_METHOD_H_ #include "InstallerMain.h" +#include "GamesList.h" void *DisplayChooseMethod(HWND hWnd); +extern game_group_t *g_game_group; + #endif //_INCLUDE_INSTALLER_CHOOSE_METHOD_H_ diff --git a/tools/installer/GamesList.cpp b/tools/installer/GamesList.cpp index 2d93c697..340b8fc3 100644 --- a/tools/installer/GamesList.cpp +++ b/tools/installer/GamesList.cpp @@ -3,8 +3,30 @@ #include "InstallerMain.h" #include -mod_info_t *g_mod_list = NULL; -unsigned int g_mod_count = 0; +game_database_t g_games = +{ + NULL, 0, + {NULL, 0, GAME_LIST_NO_GAMES}, + {NULL, 0, GAME_LIST_NO_GAMES}, + {NULL, 0, GAME_LIST_NO_GAMES} +}; + +valve_game_t valve_game_list[] = +{ + {_T("counter-strike source"), _T("cstrike"), SOURCE_ENGINE_2004}, + {_T("day of defeat source"), _T("dod"), SOURCE_ENGINE_2004}, + {_T("half-life 2 deathmatch"), _T("hl2mp"), SOURCE_ENGINE_2004}, + {_T("half-life deathmatch source"), _T("hl1mp"), SOURCE_ENGINE_2004}, + {_T("team fortress 2"), _T("tf"), SOURCE_ENGINE_2007}, + {NULL, NULL, 0}, +}; + +valve_game_t valve_server_list[] = +{ + {_T("source dedicated server"), NULL, SOURCE_ENGINE_2004}, + {_T("source 2007 dedicated server"), NULL, SOURCE_ENGINE_2007}, + {NULL, NULL, 0}, +}; int IsValidFolder(const TCHAR *path) { @@ -64,30 +86,80 @@ void DisplayBadFolderDialog(HWND hDlg, int reason) MB_OK|MB_ICONWARNING); } -void AddModToList(mod_info_t **mod_list, - unsigned int *total_mods, - const mod_info_t *mod_info) +game_list_t *MakeGameList(const TCHAR *name) { - mod_info_t *mods = *mod_list; - unsigned int total = *total_mods; + game_list_t *gl = (game_list_t *)malloc(sizeof(game_list_t)); - if (mods == NULL) + UTIL_Format(gl->root_name, + sizeof(gl->root_name) / sizeof(TCHAR), + _T("%s"), + name); + gl->game_count = 0; + gl->games = NULL; + + return gl; +} + +void AttachGameListToGroup(game_group_t *group, game_list_t *gl) +{ + if (group->lists == NULL) { - mods = (mod_info_t *)malloc(sizeof(mod_info_t)); + group->lists = (game_list_t **)malloc(sizeof(game_list_t *)); } else { - mods = (mod_info_t *)realloc(mods, sizeof(mod_info_t) * (total + 1)); + group->lists = (game_list_t **)realloc(group->lists, + sizeof(game_list_t *) * (group->list_count + 1)); } - memcpy(&mods[total], mod_info, sizeof(mod_info_t)); - total++; - - *mod_list = mods; - *total_mods = total; + group->lists[group->list_count] = gl; + group->list_count++; } -void TryToAddMod(const TCHAR *path, int eng_type, mod_info_t **mod_list, unsigned *total_mods) +void AttachModToGameList(game_list_t *gl, unsigned int mod_id) +{ + if (gl->games == NULL) + { + gl->games = (unsigned int *)malloc(sizeof(unsigned int)); + } + else + { + gl->games = (unsigned int *)realloc(gl->games, + sizeof(unsigned int) * (gl->game_count + 1)); + } + + gl->games[gl->game_count] = mod_id; + gl->game_count++; +} + +unsigned int AddModToList(game_database_t *db, const game_info_t *mod_info) +{ + /* Check if a matching game already exists */ + for (unsigned int i = 0; i < db->game_count; i++) + { + if (tstrcasecmp(mod_info->game_path, db->game_list[i].game_path) == 0) + { + return i; + } + } + + if (db->game_list == NULL) + { + db->game_list = (game_info_t *)malloc(sizeof(game_info_t)); + } + else + { + db->game_list = (game_info_t *)realloc(db->game_list, + sizeof(game_info_t) * (db->game_count + 1)); + } + + memcpy(&db->game_list[db->game_count], mod_info, sizeof(game_info_t)); + db->game_count++; + + return db->game_count - 1; +} + +bool TryToAddMod(const TCHAR *path, int eng_type, game_database_t *db, unsigned int *id) { FILE *fp; TCHAR gameinfo_path[MAX_PATH]; @@ -99,7 +171,7 @@ void TryToAddMod(const TCHAR *path, int eng_type, mod_info_t **mod_list, unsigne if ((fp = _tfopen(gameinfo_path, _T("rt"))) == NULL) { - return; + return false; } int pos; @@ -117,23 +189,41 @@ void TryToAddMod(const TCHAR *path, int eng_type, mod_info_t **mod_list, unsigne } if (strcmp(key, "game") == 0) { - mod_info_t mod; + game_info_t mod; + unsigned int got_id; + AnsiToUnicode(value, mod.name, sizeof(mod.name)); - UTIL_Format(mod.mod_path, sizeof(mod.mod_path), _T("%s"), path); + UTIL_Format(mod.game_path, sizeof(mod.game_path), _T("%s"), path); mod.source_engine = eng_type; - AddModToList(mod_list, total_mods, &mod); + + got_id = AddModToList(db, &mod); + + if (id != NULL) + { + *id = got_id; + } + + fclose(fp); + + return true; } } fclose(fp); + + return false; } -void AddModsFromFolder(const TCHAR *path, int eng_type, mod_info_t **mod_list, unsigned int *total_mods) +void AddModsFromFolder(const TCHAR *path, + int eng_type, + game_database_t *db, + game_list_t *gl) { HANDLE hFind; WIN32_FIND_DATA fd; TCHAR temp_path[MAX_PATH]; TCHAR search_path[MAX_PATH]; + unsigned int mod_id; UTIL_Format(search_path, sizeof(search_path), @@ -163,30 +253,60 @@ void AddModsFromFolder(const TCHAR *path, int eng_type, mod_info_t **mod_list, u _T("%s\\%s"), path, fd.cFileName); - TryToAddMod(temp_path, eng_type, mod_list, total_mods); - + if (TryToAddMod(temp_path, eng_type, db, &mod_id)) + { + AttachModToGameList(gl, mod_id); + } } while (FindNextFile(hFind, &fd)); FindClose(hFind); } -void AddValveModsFromFolder(const TCHAR *path, - unsigned int game_type, - mod_info_t **mod_list, - unsigned int *total_mods) +void GetSteamGames(game_database_t *db) { + HKEY hkPath; + DWORD dwLen, dwType; HANDLE hFind; WIN32_FIND_DATA fd; TCHAR temp_path[MAX_PATH]; - TCHAR search_path[MAX_PATH]; + TCHAR steam_path[MAX_PATH]; + TCHAR steamapps_path[MAX_PATH]; - UTIL_PathFormat(search_path, - sizeof(search_path) / sizeof(TCHAR), - _T("%s\\*.*"), - path); - - if ((hFind = FindFirstFile(search_path, &fd)) == INVALID_HANDLE_VALUE) + if (RegOpenKeyEx(HKEY_CURRENT_USER, + _T("Software\\Valve\\Steam"), + 0, + KEY_READ, + &hkPath) != ERROR_SUCCESS) { + db->listen.error_code = GAME_LIST_CANT_READ; + db->dedicated.error_code = GAME_LIST_CANT_READ; + return; + } + + dwLen = sizeof(steam_path) / sizeof(TCHAR); + if (RegQueryValueEx(hkPath, + _T("SteamPath"), + NULL, + &dwType, + (LPBYTE)steam_path, + &dwLen) != ERROR_SUCCESS) + { + RegCloseKey(hkPath); + db->listen.error_code = GAME_LIST_CANT_READ; + db->dedicated.error_code = GAME_LIST_CANT_READ; + return; + } + + UTIL_PathFormat(steamapps_path, + sizeof(steamapps_path) / sizeof(TCHAR), + _T("%s\\steamapps\\*.*"), + steam_path); + + if ((hFind = FindFirstFile(steamapps_path, &fd)) == INVALID_HANDLE_VALUE) + { + RegCloseKey(hkPath); + db->listen.error_code = GAME_LIST_CANT_READ; + db->dedicated.error_code = GAME_LIST_CANT_READ; return; } @@ -203,263 +323,163 @@ void AddValveModsFromFolder(const TCHAR *path, continue; } - TCHAR *mod_folder = NULL; - int eng_type = SOURCE_ENGINE_UNKNOWN; + /* If we get a folder called "SourceMods," look for third party mods */ + if (tstrcasecmp(fd.cFileName, _T("SourceMods")) == 0) + { + game_list_t *gl = MakeGameList(_T("Third-Party Games")); - if (game_type == GAMES_LISTEN) - { - if (tstrcasecmp(fd.cFileName, _T( "counter-strike source")) == 0) - { - mod_folder = _T("cstrike"); - } - else if (tstrcasecmp(fd.cFileName, _T("day of defeat source")) == 0) - { - mod_folder = _T("dod"); - } - else if (tstrcasecmp(fd.cFileName, _T("half-life 2 deathmatch")) == 0) - { - mod_folder = _T("hl2mp"); - } - else if (tstrcasecmp(fd.cFileName, _T("half-life deathmatch source")) == 0) - { - mod_folder = _T("hl1mp"); - } - else if (tstrcasecmp(fd.cFileName, _T("team fortress 2")) == 0) - { - mod_folder = _T("tf"); - eng_type = SOURCE_ENGINE_2007; - } - } - else if (game_type == GAMES_DEDICATED) - { - if (tstrcasecmp(fd.cFileName, _T("source dedicated server")) == 0) - { - UTIL_PathFormat(temp_path, - sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\%s"), - path, - fd.cFileName); - AddModsFromFolder(temp_path, SOURCE_ENGINE_2004, mod_list, total_mods); - } - else if (tstrcasecmp(fd.cFileName, _T("source 2007 dedicated server")) == 0) - { - UTIL_PathFormat(temp_path, - sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\%s"), - path, - fd.cFileName); - AddModsFromFolder(temp_path, SOURCE_ENGINE_2007, mod_list, total_mods); - } - } - - if (mod_folder != NULL) - { UTIL_PathFormat(temp_path, sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\%s\\%s"), - path, - fd.cFileName, - mod_folder); - TryToAddMod(temp_path, eng_type, mod_list, total_mods); + _T("%s\\steamapps\\%s"), + steam_path, + fd.cFileName); + + AddModsFromFolder(temp_path, SOURCE_ENGINE_UNKNOWN, db, gl); + + if (gl->game_count) + { + AttachGameListToGroup(&db->listen, gl); + } + else + { + free(gl); + } + } + else + { + /* Look for listenserver games */ + game_list_t *gl = MakeGameList(fd.cFileName); + + for (unsigned int i = 0; valve_game_list[i].folder != NULL; i++) + { + unsigned int mod_id; + UTIL_PathFormat(temp_path, + sizeof(temp_path) / sizeof(TCHAR), + _T("%s\\steamapps\\%s\\%s\\%s"), + steam_path, + fd.cFileName, + valve_game_list[i].folder, + valve_game_list[i].subfolder); + if (TryToAddMod(temp_path, valve_game_list[i].eng_type, db, &mod_id)) + { + AttachModToGameList(gl, mod_id); + } + } + + if (gl->game_count) + { + AttachGameListToGroup(&db->listen, gl); + } + else + { + free(gl); + } + + /* Look for dedicated games */ + gl = MakeGameList(fd.cFileName); + + for (unsigned int i = 0; valve_server_list[i].folder != NULL; i++) + { + UTIL_PathFormat(temp_path, + sizeof(temp_path) / sizeof(TCHAR), + _T("%s\\steamapps\\%s\\%s"), + steam_path, + fd.cFileName, + valve_server_list[i].folder); + AddModsFromFolder(temp_path, valve_server_list[i].eng_type, db, gl); + } + + if (gl->game_count) + { + AttachGameListToGroup(&db->dedicated, gl); + } + else + { + free(gl); + } } } while (FindNextFile(hFind, &fd)); FindClose(hFind); + RegCloseKey(hkPath); } -int BuildGameList(unsigned int game_type, mod_info_t **mod_list) +void GetStandaloneGames(game_database_t *db) { - unsigned int total_mods = 0; - - if (game_type == GAMES_LISTEN - || game_type == GAMES_DEDICATED) - { - HKEY hkPath; - DWORD dwLen, dwType; - HANDLE hFind; - WIN32_FIND_DATA fd; - TCHAR temp_path[MAX_PATH]; - TCHAR steam_path[MAX_PATH]; - TCHAR steamapps_path[MAX_PATH]; - - if (RegOpenKeyEx(HKEY_CURRENT_USER, - _T("Software\\Valve\\Steam"), - 0, - KEY_READ, - &hkPath) != ERROR_SUCCESS) - { - DWORD err = GetLastError(); - return GAME_LIST_CANT_READ; - } - - dwLen = sizeof(steam_path) / sizeof(TCHAR); - if (RegQueryValueEx(hkPath, - _T("SteamPath"), - NULL, - &dwType, - (LPBYTE)steam_path, - &dwLen) != ERROR_SUCCESS) - { - RegCloseKey(hkPath); - return GAME_LIST_CANT_READ; - } - - UTIL_PathFormat(steamapps_path, - sizeof(steamapps_path) / sizeof(TCHAR), - _T("%s\\steamapps\\*.*"), - steam_path); - - if ((hFind = FindFirstFile(steamapps_path, &fd)) == INVALID_HANDLE_VALUE) - { - RegCloseKey(hkPath); - return GAME_LIST_CANT_READ; - } - - do - { - if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) - { - continue; - } - - if (tstrcasecmp(fd.cFileName, _T(".")) == 0 - || tstrcasecmp(fd.cFileName, _T("..")) == 0) - { - continue; - } - - /* If we get a folder called "SourceMods," look for third party mods */ - if (game_type == GAMES_LISTEN - && tstrcasecmp(fd.cFileName, _T("SourceMods")) == 0) - { - UTIL_PathFormat(temp_path, - sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\steamapps\\%s"), - steam_path, - fd.cFileName); - AddModsFromFolder(temp_path, SOURCE_ENGINE_UNKNOWN, mod_list, &total_mods); - } - else - { - UTIL_PathFormat(temp_path, - sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\steamapps\\%s"), - steam_path, - fd.cFileName); - AddValveModsFromFolder(temp_path, game_type, mod_list, &total_mods); - } - - } while (FindNextFile(hFind, &fd)); - - FindClose(hFind); - RegCloseKey(hkPath); - } - else if (game_type == GAMES_STANDALONE) - { - HKEY hkPath; - int eng_type = SOURCE_ENGINE_UNKNOWN; - DWORD dwLen, dwType, dwAttr; - TCHAR temp_path[MAX_PATH]; - TCHAR hlds_path[MAX_PATH]; - - if (RegOpenKeyEx(HKEY_CURRENT_USER, - _T("Software\\Valve\\HLServer"), - 0, - KEY_READ, - &hkPath) != ERROR_SUCCESS) - { - return GAME_LIST_CANT_READ; - } - - dwLen = sizeof(hlds_path) / sizeof(TCHAR); - if (RegQueryValueEx(hkPath, - _T("InstallPath"), - NULL, - &dwType, - (LPBYTE)hlds_path, - &dwLen) != ERROR_SUCCESS) - { - RegCloseKey(hkPath); - return GAME_LIST_CANT_READ; - } - - /* Make sure there is a "srcds.exe" file */ - UTIL_PathFormat(temp_path, - sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\srcds.exe"), - hlds_path); - dwAttr = GetFileAttributes(temp_path); - if (dwAttr == INVALID_FILE_ATTRIBUTES) - { - return GAME_LIST_HALFLIFE1; - } - - /* If there is an "orangebox" sub folder, we can make a better guess - * at the engine state. - */ - UTIL_PathFormat(temp_path, - sizeof(temp_path) / sizeof(TCHAR), - _T("%s\\orangebox"), - hlds_path); - dwAttr = GetFileAttributes(temp_path); - if (dwAttr != INVALID_FILE_ATTRIBUTES - && ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) - { - eng_type = SOURCE_ENGINE_2004; - AddModsFromFolder(temp_path, SOURCE_ENGINE_2007, mod_list, &total_mods); - } - - /* Add everything from the server */ - AddModsFromFolder(hlds_path, eng_type, mod_list, &total_mods); - - RegCloseKey(hkPath); - } - - return (g_mod_list == NULL) ? GAME_LIST_NO_GAMES : (int)total_mods; -} - -void FreeGameList(mod_info_t *mod_list) -{ - free(mod_list); -} - -int _SortModList(const void *item1, const void *item2) -{ - const mod_info_t *mod1 = (const mod_info_t *)item1; - const mod_info_t *mod2 = (const mod_info_t *)item2; - - return tstrcasecmp(mod1->name, mod2->name); -} - -int FindGames(unsigned int game_type) -{ - int reason; - - ReleaseGamesList(); - - if ((reason = BuildGameList(game_type, &g_mod_list)) > 0) - { - g_mod_count = (unsigned)reason; - qsort(g_mod_list, g_mod_count, sizeof(mod_info_t), _SortModList); - } - - return reason; -} - -void ReleaseGamesList() -{ - if (g_mod_list == NULL) + HKEY hkPath; + DWORD dwLen, dwType, dwAttr; + TCHAR temp_path[MAX_PATH]; + TCHAR hlds_path[MAX_PATH]; + game_list_t *games_standalone; + + if (RegOpenKeyEx(HKEY_CURRENT_USER, + _T("Software\\Valve\\HLServer"), + 0, + KEY_READ, + &hkPath) != ERROR_SUCCESS) { + db->standalone.error_code = GAME_LIST_CANT_READ; return; } - free(g_mod_list); - g_mod_list = NULL; - g_mod_count = 0; + dwLen = sizeof(hlds_path) / sizeof(TCHAR); + if (RegQueryValueEx(hkPath, + _T("InstallPath"), + NULL, + &dwType, + (LPBYTE)hlds_path, + &dwLen) != ERROR_SUCCESS) + { + RegCloseKey(hkPath); + db->standalone.error_code = GAME_LIST_CANT_READ; + return; + } + + /* Make sure there is a "srcds.exe" file */ + UTIL_PathFormat(temp_path, + sizeof(temp_path) / sizeof(TCHAR), + _T("%s\\srcds.exe"), + hlds_path); + dwAttr = GetFileAttributes(temp_path); + if (dwAttr == INVALID_FILE_ATTRIBUTES) + { + db->standalone.error_code = GAME_LIST_HALFLIFE1; + return; + } + + games_standalone = MakeGameList(_T("Standalone")); + + /* If there is an "orangebox" sub folder, we can make a better guess + * at the engine state. + */ + UTIL_PathFormat(temp_path, + sizeof(temp_path) / sizeof(TCHAR), + _T("%s\\orangebox"), + hlds_path); + dwAttr = GetFileAttributes(temp_path); + if (dwAttr != INVALID_FILE_ATTRIBUTES + && ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) + { + AddModsFromFolder(temp_path, SOURCE_ENGINE_2007, db, games_standalone); + } + + /* Add everything from the server */ + AddModsFromFolder(hlds_path, SOURCE_ENGINE_2004, db, games_standalone); + + if (games_standalone->game_count) + { + AttachGameListToGroup(&db->standalone, games_standalone); + } + else + { + free(games_standalone); + } + + RegCloseKey(hkPath); } -void DisplayBadGamesDialog(HWND hWnd, unsigned int game_type, int reason) +void DisplayBadGamesDialog(HWND hWnd, int reason) { TCHAR message[256]; UINT idc = 0; @@ -494,3 +514,61 @@ void DisplayBadGamesDialog(HWND hWnd, unsigned int game_type, int reason) _T("SourceMod Installer"), MB_OK|MB_ICONWARNING); } + +int _ModIdCompare(const void *item1, const void *item2) +{ + unsigned int mod_id1 = *(unsigned int *)item1; + unsigned int mod_id2 = *(unsigned int *)item2; + + return tstrcasecmp(g_games.game_list[mod_id1].name, g_games.game_list[mod_id2].name); +} + +int _GroupCompare(const void *item1, const void *item2) +{ + game_list_t *g1 = *(game_list_t **)item1; + game_list_t *g2 = *(game_list_t **)item2; + + return tstrcasecmp(g1->root_name, g2->root_name); +} + +void SortGameGroup(game_group_t *group) +{ + qsort(group->lists, group->list_count, sizeof(game_list_t *), _GroupCompare); + + for (unsigned int i = 0; i < group->list_count; i++) + { + qsort(group->lists[i]->games, + group->lists[i]->game_count, + sizeof(unsigned int), + _ModIdCompare); + } +} + +void BuildGameDB() +{ + ReleaseGameDB(); + GetStandaloneGames(&g_games); + GetSteamGames(&g_games); + SortGameGroup(&g_games.dedicated); + SortGameGroup(&g_games.listen); + SortGameGroup(&g_games.standalone); +} + +void ReleaseGameGroup(game_group_t *group) +{ + for (unsigned int i = 0; i < group->list_count; i++) + { + free(group->lists[i]->games); + free(group->lists[i]); + } + free(group->lists); +} + +void ReleaseGameDB() +{ + ReleaseGameGroup(&g_games.dedicated); + ReleaseGameGroup(&g_games.listen); + ReleaseGameGroup(&g_games.standalone); + free(g_games.game_list); + memset(&g_games, 0, sizeof(g_games)); +} diff --git a/tools/installer/GamesList.h b/tools/installer/GamesList.h index 5b26fadb..2242575a 100644 --- a/tools/installer/GamesList.h +++ b/tools/installer/GamesList.h @@ -19,21 +19,54 @@ #define SOURCE_ENGINE_2004 1 #define SOURCE_ENGINE_2007 2 -struct mod_info_t +struct valve_game_t +{ + const TCHAR *folder; + const TCHAR *subfolder; + int eng_type; +}; + +/* One game */ +struct game_info_t { TCHAR name[128]; - TCHAR mod_path[MAX_PATH]; + TCHAR game_path[MAX_PATH]; int source_engine; }; +/* A list of games under one "account" */ +struct game_list_t +{ + TCHAR root_name[128]; + unsigned int *games; + unsigned int game_count; +}; + +/* A list of accounts */ +struct game_group_t +{ + game_list_t **lists; + unsigned int list_count; + int error_code; +}; + +/* All games on the system */ +struct game_database_t +{ + game_info_t *game_list; + unsigned int game_count; + game_group_t dedicated; + game_group_t listen; + game_group_t standalone; +}; + int IsValidFolder(const TCHAR *path); void DisplayBadFolderDialog(HWND hWnd, int reason); -int FindGames(unsigned int game_type); -void DisplayBadGamesDialog(HWND hWnd, unsigned int game_type, int reason); -void ReleaseGamesList(); +void BuildGameDB(); +void ReleaseGameDB(); +void DisplayBadGamesDialog(HWND hWnd, int reason); -extern mod_info_t *g_mod_list; -extern unsigned int g_mod_count; +extern game_database_t g_games; #endif //_INCLUDE_INSTALLER_GAMES_LIST_H_ diff --git a/tools/installer/Resource.h b/tools/installer/Resource.h index f47b0ac0..7ab83304 100644 --- a/tools/installer/Resource.h +++ b/tools/installer/Resource.h @@ -44,6 +44,8 @@ #define ID_INSTALL_CANCEL 1019 #define IDC_INSTALL_PANEL 1020 #define IDC_INSTALL_TEXT 1021 +#define IDC_COMBO3 1021 +#define IDC_SELGROUP_ACCOUNT 1021 #define ID_INSTALL_START 1022 #define IDC_PROGRESS_CURCOPY 1023 #define IDC_STATIC -1 @@ -57,7 +59,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 133 #define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1012 +#define _APS_NEXT_CONTROL_VALUE 1022 #define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/tools/installer/SelectGame.cpp b/tools/installer/SelectGame.cpp index cd983f04..d90153e5 100644 --- a/tools/installer/SelectGame.cpp +++ b/tools/installer/SelectGame.cpp @@ -7,50 +7,56 @@ #include "LocalCopyMethod.h" int selected_game_index = -1; -mod_info_t **game_sel_list = NULL; -unsigned int game_sel_count = 0; -void AppendSelectableGame(mod_info_t *mod) +void UpdateGameListBox(HWND hDlg, game_list_t *gl) { - if (game_sel_list == NULL) - { - game_sel_list = - (mod_info_t **)malloc(sizeof(mod_info_t *) * (game_sel_count + 1)); - } - else - { - game_sel_list = - (mod_info_t **)realloc(game_sel_list, - sizeof(mod_info_t *) * (game_sel_count + 1)); - } + HWND lbox = GetDlgItem(hDlg, IDC_SELGAME_LIST); - game_sel_list[game_sel_count++] = mod; + SendMessage(lbox, LB_RESETCONTENT, 0, 0); + + for (unsigned int i = 0; i < gl->game_count; i++) + { + LRESULT res = SendMessage(lbox, + LB_ADDSTRING, + 0, + (LPARAM)g_games.game_list[gl->games[i]].name); + + if (res == LB_ERR || res == LB_ERRSPACE) + { + continue; + } + + SendMessage(lbox, LB_SETITEMDATA, i, gl->games[i]); + } + + UpdateWindow(lbox); } +#include "windowsx.h" + INT_PTR CALLBACK ChooseGameHandler(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: { - HWND lbox = GetDlgItem(hDlg, IDC_SELGAME_LIST); - - for (unsigned int i = 0; i < g_mod_count; i++) + HWND cbox = GetDlgItem(hDlg, IDC_SELGROUP_ACCOUNT); + SendMessage(cbox, CB_RESETCONTENT, 0, 0); + for (unsigned int i = 0; i < g_game_group->list_count; i++) { - LRESULT res = SendMessage(lbox, - LB_ADDSTRING, - 0, - (LPARAM)g_mod_list[i].name); - - if (res == LB_ERR || res == LB_ERRSPACE) + LRESULT res = SendMessage(cbox, + CB_ADDSTRING, + 0, + (LPARAM)g_game_group->lists[i]->root_name); + if (res == CB_ERR || res == CB_ERRSPACE) { continue; } - - AppendSelectableGame(&g_mod_list[i]); + SendMessage(cbox, CB_SETITEMDATA, i, (LPARAM)g_game_group->lists[i]); } - - UpdateWindow(lbox); + SendMessage(cbox, CB_SETCURSEL, 0, 0); + UpdateWindow(cbox); + UpdateGameListBox(hDlg, g_game_group->lists[0]); SetToGlobalPosition(hDlg); @@ -69,6 +75,29 @@ INT_PTR CALLBACK ChooseGameHandler(HWND hDlg, UINT message, WPARAM wParam, LPARA EndDialog(hDlg, (INT_PTR)DisplayChooseMethod); return (INT_PTR)TRUE; } + else if (LOWORD(wParam) == IDC_SELGROUP_ACCOUNT) + { + if (HIWORD(wParam) == CBN_SELCHANGE) + { + HWND cbox = (HWND)lParam; + LRESULT cursel = SendMessage(cbox, CB_GETCURSEL, 0, 0); + + if (cursel == LB_ERR) + { + break; + } + + LRESULT data = SendMessage(cbox, CB_GETITEMDATA, cursel, 0); + if (data == CB_ERR) + { + break; + } + + game_list_t *gl = (game_list_t *)data; + UpdateGameListBox(hDlg, gl); + } + break; + } else if (LOWORD(wParam) == IDC_SELGAME_LIST) { if (HIWORD(wParam) == LBN_SELCHANGE) @@ -83,12 +112,13 @@ INT_PTR CALLBACK ChooseGameHandler(HWND hDlg, UINT message, WPARAM wParam, LPARA break; } - if (cursel >= (LRESULT)g_mod_count) + LRESULT item = SendMessage(lbox, LB_GETITEMDATA, cursel, 0); + if (item == LB_ERR) { break; } - selected_game_index = (int)cursel; + selected_game_index = (int)item; HWND button = GetDlgItem(hDlg, ID_SELGAME_NEXT); EnableWindow(button, TRUE); @@ -101,7 +131,7 @@ INT_PTR CALLBACK ChooseGameHandler(HWND hDlg, UINT message, WPARAM wParam, LPARA break; } - g_LocalCopier.SetOutputPath(game_sel_list[selected_game_index]->mod_path); + g_LocalCopier.SetOutputPath(g_games.game_list[selected_game_index].game_path); SetInstallMethod(&g_LocalCopier); UpdateGlobalPosition(hDlg); @@ -113,10 +143,7 @@ INT_PTR CALLBACK ChooseGameHandler(HWND hDlg, UINT message, WPARAM wParam, LPARA } case WM_DESTROY: { - ReleaseGamesList(); - free(game_sel_list); - game_sel_list = NULL; - game_sel_count = 0; + ReleaseGameDB(); break; } } diff --git a/tools/installer/installer.rc b/tools/installer/installer.rc index be5d9eb8..51287cd1 100644 --- a/tools/installer/installer.rc +++ b/tools/installer/installer.rc @@ -99,18 +99,19 @@ BEGIN CONTROL "Upload via FTP",IDC_METHOD_UPLOAD_FTP,"Button",BS_AUTORADIOBUTTON,21,82,94,16 END -IDD_SELECT_GAME DIALOGEX 0, 0, 244, 130 +IDD_SELECT_GAME DIALOGEX 0, 0, 244, 148 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "SourceMod Installer" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - PUSHBUTTON "&Next",ID_SELGAME_NEXT,191,113,50,14,WS_DISABLED - PUSHBUTTON "E&xit",ID_SELGAME_EXIT,2,113,50,14 - GROUPBOX "",IDC_SELGAME_PANEL,2,3,239,108 - DEFPUSHBUTTON "&Back",ID_SELGAME_BACK,136,113,50,14 - LTEXT "Please select a game:",IDC_SELGAME_TEXT,9,15,122,12 - LISTBOX IDC_SELGAME_LIST,17,30,199,69,LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Next",ID_SELGAME_NEXT,191,131,50,14,WS_DISABLED + PUSHBUTTON "E&xit",ID_SELGAME_EXIT,2,131,50,14 + GROUPBOX "",IDC_SELGAME_PANEL,2,3,239,126 + DEFPUSHBUTTON "&Back",ID_SELGAME_BACK,136,131,50,14 + LTEXT "Please select a game from the list below. If there are multiple accounts, you may select one from the combo-box.",IDC_SELGAME_TEXT,7,14,221,16 + LISTBOX IDC_SELGAME_LIST,17,46,199,76,LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_SELGROUP_ACCOUNT,17,32,133,80,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END IDD_PERFORM_INSTALL DIALOGEX 0, 0, 243, 116