From 58d420861f5fda35913aa14f672f4ce43db7da57 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Sun, 6 Sep 2020 08:37:36 +0200 Subject: [PATCH] Menu: Integrated package manager functions into the Custom game menu. Mods and so on will now be installed remotely from there. --- src/menu-fn/defs.h | 1 + src/menu-fn/entry.cpp | 8 +- src/menu-fn/m_customgame.cpp | 206 ++++++++++++++++++++++++++++++++--- src/menu-fn/m_updates.cpp | 7 +- src/menu-fn/modserver.cpp | 7 ++ src/menu-fn/w_updatelist.cpp | 15 ++- 6 files changed, 222 insertions(+), 22 deletions(-) diff --git a/src/menu-fn/defs.h b/src/menu-fn/defs.h index e4a725c4..e9dc122e 100644 --- a/src/menu-fn/defs.h +++ b/src/menu-fn/defs.h @@ -61,6 +61,7 @@ typedef struct string type; string hlversion; string pkgname; + int pkgid; int nomodels; int installed; string mpentity; diff --git a/src/menu-fn/entry.cpp b/src/menu-fn/entry.cpp index a30b0579..6ad8f353 100644 --- a/src/menu-fn/entry.cpp +++ b/src/menu-fn/entry.cpp @@ -121,14 +121,18 @@ m_init(void) Strings_Init(); g_initialized = TRUE; - /*if (cvar_string("game") != "valve")*/ { + if (cvar_string("game") != "valve") { m_intro_skip(); Music_MenuStart(); } - + if (autocvar_menu_updating || !autocvar_menu_installedpackages) { g_menupage = PAGE_UPDATES; } + if (g_iModInstallCache >= 0) { + g_menupage = PAGE_CUSTOMGAME; + } + Menu_AutoScale(); Menu_GammaHack(); } diff --git a/src/menu-fn/m_customgame.cpp b/src/menu-fn/m_customgame.cpp index 174b3e7c..7d68246b 100644 --- a/src/menu-fn/m_customgame.cpp +++ b/src/menu-fn/m_customgame.cpp @@ -14,6 +14,84 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* the menu specific variables */ +CWidget fn_customgame; +CFrame customgame_frMods; +CModList customgame_lbMods; +CScrollbar customgame_sbMods; +CDialog customgame_dlgWait; + +CMainButton customgame_btnActivate; +CMainButton customgame_btnInstall; +CMainButton customgame_btnVisit; +CMainButton customgame_btnRefresh; +CMainButton customgame_btnDeactivate; +CMainButton customgame_btnDone; + +/* get package id */ +var int g_iModInstallCache; +var string g_strModInstallCache; + +int +game_getpackageid(string pkgname) +{ + string f; + + for (int i = 0; (getpackagemanagerinfo(i, GPMI_NAME)); i++) { + string name; + name = getpackagemanagerinfo(i, GPMI_NAME); + + /* Spike started randomly putting version numbers into package names */ + f = sprintf("%s=%s", pkgname, getpackagemanagerinfo(i, GPMI_VERSION)); + + if (name == f) { + return i; + } + } + + /* no package id whatsoever */ + return -1; +} + +/* get installing id */ +void +game_getinstallcache(void) +{ + int ret; + filestream fs_cache; + + ret = 0; + fs_cache = fopen("mcache.dat", FILE_READ); + + if (fs_cache >= 0) { + g_iModInstallCache = (int)stof(fgets(fs_cache)); + g_strModInstallCache = fgets(fs_cache); + fclose(fs_cache); + } else { + g_iModInstallCache = -1; + g_strModInstallCache = ""; + } + + print(sprintf("id: %i, name: %s\n", ret, g_strModInstallCache)); +} + +/* write installing id */ +void +game_writeinstallcache(int id, string gamedir) +{ + filestream fs_cache; + + fs_cache = fopen("mcache.dat", FILE_WRITE); + g_iModInstallCache = id; + g_strModInstallCache = gamedir; + + if (fs_cache >= 0) { + fputs(fs_cache, sprintf("%i\n",id)); + fputs(fs_cache, gamedir); + fclose(fs_cache); + } +} + /* local game/mod info parsing */ void games_set(int id) @@ -80,6 +158,7 @@ games_init(void) games[id].svonly = 0; games[id].installed = 1; games[id].chatroom = gamedirname; + games[id].pkgid = -1; for (int i = 0; i < county; i++) { switch(argv(i)) { @@ -113,12 +192,14 @@ games_init(void) case "gameinfo_type": switch (strtolower(argv(i+1))) { case "multiplayer_only": + case "multiplayer only": case "mp": case "multi": case "multiplayer": games[id].type = "Multiplayer"; break; case "singleplayer_only": + case "singleplayer only": case "sp": case "single": case "singleplayer": @@ -151,6 +232,7 @@ games_init(void) break; case "gameinfo_pkgname": games[id].pkgname = argv(i+1); + games[id].pkgid = game_getpackageid(games[id].pkgname); break; case "gameinfo_chatroom": games[id].chatroom = argv(i+1); @@ -164,6 +246,8 @@ games_init(void) } } + game_getinstallcache(); + if (gameinfo_current == -1) { print("^1FATAL ERROR: NO MODINFO.TXT FOR CURRENT MOD FOUND!\n"); crash(); @@ -171,19 +255,92 @@ games_init(void) } } -/* the menu specific code */ -CWidget fn_customgame; -CFrame customgame_frMods; -CModList customgame_lbMods; -CScrollbar customgame_sbMods; -CDialog customgame_dlgWait; +void +customgame_installstart(int gameid) +{ + int count; + count = tokenize(games[gameid].pkgname); -CMainButton customgame_btnActivate; -CMainButton customgame_btnInstall; -CMainButton customgame_btnVisit; -CMainButton customgame_btnRefresh; -CMainButton customgame_btnDeactivate; -CMainButton customgame_btnDone; + for (int i = 0; i < count; i++) { + int pkgid = game_getpackageid(argv(i)); + localcmd(sprintf("pkg add %s\n", argv(i))); + print(sprintf("Marking package %s for install.\n", + argv(i))); + } + + game_writeinstallcache(gameid, games[gameid].gamedir); + localcmd("pkg apply\n"); + print("Starting installation of custom game packages\n"); +} + +void +customgame_installend(void) +{ + int gid = g_iModInstallCache; + print("install-end!\n"); + + localcmd(sprintf("fs_changegame %s http://www.frag-net.com/mods/%s.fmf\n", g_strModInstallCache, g_strModInstallCache)); + game_writeinstallcache(-1, g_strModInstallCache); +} + +void +customgame_installframe(void) +{ + int id; + float perc; + float c; + int loading; + + /* graphical frame */ + customgame_dlgWait.Draw(); + WField_Static(162, 180, "Installing mod data...", 320, 260, + col_prompt_text, 1.0f, 2, font_label_p); + + /* download percentage */ + perc = 0.0f; + loading = FALSE; + + /* a game can have multiple packages associated */ + id = g_iModInstallCache; + c = tokenize(games[id].pkgname); + + /* go through all invididual packages */ + for (float i = 0; i < c; i++) { + string st; + int pkgid; + + /* package query */ + pkgid = game_getpackageid(argv(i)); + st = getpackagemanagerinfo(pkgid, GPMI_INSTALLED); + + /* filter out statuses so we can calculate percentage */ + switch (st) { + case "": + case "pending": + case "enabled": + case "present": + case "corrupt": + break; + default: + perc += stof(st); + } + + /* all packages need to be 'enabled', else fail to end */ + if (st != "enabled") + loading = TRUE; + } + + /* display download percentage we calculated */ + perc = perc / c; + WField_Static(162, 220, sprintf("%d", perc), 320, 260, + col_prompt_text, 1.0f, 2, font_label_p); + + /* not everything has been downloaded */ + if (loading == TRUE) + return; + + customgame_installend(); +} void customgame_btnactivate_start(void) @@ -210,9 +367,21 @@ customgame_btnactivate_start(void) void customgame_btninstall_start(void) { - int gid = customgame_lbMods.GetSelected(); - print(sprintf("Requesting download for http://www.frag-net.com/mods/%s.fmf...\n", games[gid].gamedir)); - localcmd(sprintf("fs_changegame %s http://www.frag-net.com/mods/%s.fmf\n", games[gid].gamedir, games[gid].gamedir)); + int id = customgame_lbMods.GetSelected(); + string st; + + st = getpackagemanagerinfo(games[id].pkgid, GPMI_INSTALLED); + + print(st); + print("\n"); + + if (st != "enabled") { + customgame_installstart(id); + return; + } + + game_writeinstallcache(id, games[id].gamedir); + customgame_installend(); } void @@ -348,10 +517,15 @@ menu_customgame_draw(void) col_prompt_text, 1.0f, 2, font_label_p); } customgame_sbMods.SetMax(gameinfo_count-1); /* don't show our current game */ + + if (g_iModInstallCache >= 0) { + customgame_installframe(); + } } void menu_customgame_input(float evtype, float scanx, float chary, float devid) { - Widget_Input(fn_customgame, evtype, scanx, chary, devid); + if (g_iModInstallCache == -1) + Widget_Input(fn_customgame, evtype, scanx, chary, devid); } diff --git a/src/menu-fn/m_updates.cpp b/src/menu-fn/m_updates.cpp index 83843118..c39ff7a3 100644 --- a/src/menu-fn/m_updates.cpp +++ b/src/menu-fn/m_updates.cpp @@ -197,7 +197,7 @@ menu_updates_refresh(void) if (cat == "Plugins/") { continue; } - if (cat == "Mods/") { + if (cat == "Mod/") { continue; } update_count++; @@ -211,7 +211,7 @@ menu_updates_refresh(void) if (cat == "Plugins/") { continue; } - if (cat == "Mods/") { + if (cat == "Mod/") { continue; } @@ -231,6 +231,7 @@ menu_updates_refresh(void) c++; } up_sbUpdates.SetMax(update_count); + up_lbUpdates.SetMax(update_count); up_lbUpdates.SetSelected(0); } @@ -249,7 +250,7 @@ menu_updates_draw(void) if (cat == "Plugins/") { continue; } - if (cat == "Mods/") { + if (cat == "Mod/") { continue; } pkg_ready = 1; diff --git a/src/menu-fn/modserver.cpp b/src/menu-fn/modserver.cpp index cb5b1ef9..eae07109 100644 --- a/src/menu-fn/modserver.cpp +++ b/src/menu-fn/modserver.cpp @@ -22,6 +22,8 @@ var int g_iModServerLoading; var int g_iModServerReqCount; +int game_getpackageid(string pkgname); + void* memrealloc(__variant *oldptr, int elementsize, int old_num, int new_num) { @@ -114,6 +116,7 @@ ModServer_ParseItem(string data) games[id].hlversion = "1110"; games[id].svonly = 0; games[id].installed = 0; + games[id].pkgid = -1; for (int i = 0; i < c; i++) { switch(argv(i)) { @@ -165,6 +168,10 @@ ModServer_ParseItem(string data) case "gameinfo_trainingmap": games[id].trainingmap = argv(i+1); break; + case "gameinfo_pkgname": + games[id].pkgname = argv(i+1); + games[id].pkgid = game_getpackageid(games[id].pkgname); + break; default: break; } diff --git a/src/menu-fn/w_updatelist.cpp b/src/menu-fn/w_updatelist.cpp index 6081618d..1bd25c93 100644 --- a/src/menu-fn/w_updatelist.cpp +++ b/src/menu-fn/w_updatelist.cpp @@ -24,7 +24,7 @@ class CUpdateList:CWidget { int m_size[2]; - + int m_max; int m_scroll; int m_selected; virtual void(void) m_changed = 0; @@ -56,6 +56,10 @@ CUpdateList::Draw(void) [0,0,0], 1.0f); visible = floor(m_size[1] / 18); + + if (visible > m_max) + visible = m_max; + pos = m_y; for (int i = m_scroll; i < (visible + m_scroll); i++) { @@ -129,6 +133,9 @@ CUpdateList::Input(float type, float x, float y, float devid) visible = floor(m_size[1] / 18); + if (visible > m_max) + visible = m_max; + pos[0] = m_x; pos[1] = m_y; @@ -193,6 +200,12 @@ CUpdateList::SetSelected(int i) } } +void +CUpdateList::SetMax(int i) +{ + m_max = i; +} + int CUpdateList::GetSelected(void) {