From 66f56bbba31c1351f92c29d4ac7fa1bc1007787c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sat, 29 Apr 2017 16:40:07 +0100 Subject: [PATCH] * Menu always updates for file load... by doing the refresh in the drawing function, eep. Oh well. * M_StartMessages when file loading goes wrong! (Determined by CONS_Alerts of warning level CONS_WARNING and CONS_ERROR happening after W_LoadWadFile has been called.) * Now actively tries to keep your place on the menu if files are deleted between calls to preparefilemenu(). * More enums! DIR_ (for if you want to try embed more metadata in the dirmenu strings) and REFRESHDIR_ (for refreshing the menu and handling warnings). * Handle changing size menu between calls to opendir() better. * Don't crash on draw/enter attempt if one of the dirmenu's is null. * Moved the addons menu to OP_MainMenu instead of MainMenu for now so it can be tested in MP without needing to mess with several menus. * Display the amount of space used for serverinfo_pak's fileneeded on the addons menu, both visually and with a percentage. --- src/console.c | 4 ++ src/d_clisrv.h | 3 +- src/d_main.c | 3 + src/filesrch.c | 55 ++++++++++++--- src/filesrch.h | 21 +++++- src/m_menu.c | 178 ++++++++++++++++++++++++++++++++----------------- src/w_wad.c | 21 +++--- 7 files changed, 201 insertions(+), 84 deletions(-) diff --git a/src/console.c b/src/console.c index 3702dd560..dcff2d656 100644 --- a/src/console.c +++ b/src/console.c @@ -33,6 +33,7 @@ #include "i_system.h" #include "d_main.h" #include "m_menu.h" +#include "filesrch.h" #ifdef _WINDOWS #include "win32/win_main.h" @@ -1275,12 +1276,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...) switch (level) { case CONS_NOTICE: + // no notice for notices, hehe CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:")); break; case CONS_WARNING: + refreshdirmenu |= REFRESHDIR_WARNING; CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:")); break; case CONS_ERROR: + refreshdirmenu |= REFRESHDIR_ERROR; CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:")); break; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 1ca82fdc5..da077c682 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -315,6 +315,7 @@ typedef struct } ATTRPACK clientconfig_pak; #define MAXSERVERNAME 32 +#define MAXFILENEEDED 915 // This packet is too large typedef struct { @@ -336,7 +337,7 @@ typedef struct unsigned char mapmd5[16]; UINT8 actnum; UINT8 iszone; - UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h) + UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) } ATTRPACK serverinfo_pak; typedef struct diff --git a/src/d_main.c b/src/d_main.c index 0bba9dc06..94775557e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "m_cond.h" // condition initialization #include "fastcmp.h" #include "keys.h" +#include "filesrch.h" // refreshdirmenu #ifdef CMAKECONFIG #include "config.h" @@ -586,6 +587,8 @@ void D_SRB2Loop(void) realtics = entertic - oldentertics; oldentertics = entertic; + refreshdirmenu = 0; // not sure where to put this, here as good as any? + #ifdef DEBUGFILE if (!realtics) if (debugload) diff --git a/src/filesrch.c b/src/filesrch.c index d3e5e5ec3..9828c9f25 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -294,6 +294,9 @@ size_t menudepthleft = menudepth; char **dirmenu; size_t sizedirmenu; size_t dir_on[menudepth]; +UINT8 refreshdirmenu = 0; + +size_t packetsizetally = 0; #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, @@ -479,12 +482,16 @@ char exttable[NUM_EXT_TABLE][5] = { char filenamebuf[MAX_WADFILES][MAX_WADPATH]; -boolean preparefilemenu(void) +boolean preparefilemenu(boolean samemenu) { DIR *dirhandle; struct dirent *dent; struct stat fsstat; size_t pos = 0, folderpos = 0, numfolders = 0; + char *tempname = NULL; + + if (samemenu && dirmenu && dirmenu[dir_on[menudepthleft]]) + tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL for (; sizedirmenu > 0; sizedirmenu--) { @@ -516,7 +523,7 @@ boolean preparefilemenu(void) ; // was the file (re)moved? can't stat it else // is a file or directory { - if (!S_ISDIR(fsstat.st_mode)) + if (!S_ISDIR(fsstat.st_mode)) // file { size_t len = strlen(dent->d_name)+1; UINT8 ext; @@ -524,7 +531,7 @@ boolean preparefilemenu(void) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file } - else + else // directory numfolders++; sizedirmenu++; } @@ -533,7 +540,11 @@ boolean preparefilemenu(void) closedir(dirhandle); // I don't know how to go back to the start of the folder without just opening and closing... if there's a way, it doesn't appear to be easily manipulatable if (!sizedirmenu) + { + if (tempname) + Z_Free(tempname); return false; + } if (menudepthleft != menudepth-1) { @@ -573,6 +584,7 @@ boolean preparefilemenu(void) if (!S_ISDIR(fsstat.st_mode)) // file { + if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention for (; ext < NUM_EXT_TABLE; ext++) if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file @@ -598,17 +610,17 @@ boolean preparefilemenu(void) folder = 0; } - else + else // directory len += (folder = 1); if (len > 255) len = 255; - if (!(temp = Z_Malloc((len+2+folder) * sizeof (char), PU_STATIC, NULL))) + if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL))) I_Error("Ran out of memory whilst preparing add-ons menu"); - temp[0] = ext; - temp[1] = (UINT8)(len); - strlcpy(temp+2, dent->d_name, len); + temp[DIR_TYPE] = ext; + temp[DIR_LEN] = (UINT8)(len); + strlcpy(temp+DIR_STRING, dent->d_name, len); if (folder) { strcpy(temp+len, "/"); @@ -620,15 +632,36 @@ boolean preparefilemenu(void) } if (menudepthleft != menudepth-1) - dirmenu[0] = Z_StrDup("\1\7\x1A UP..."); + dirmenu[0] = Z_StrDup("\1\5UP..."); menupath[menupathindex[menudepthleft]] = 0; - sizedirmenu = (pos+folderpos); // crash prevention if things change between openings somehow + sizedirmenu = (numfolders+pos); // crash prevention if things change between openings somehow + + if (tempname) + { + size_t i; + for (i = 0; i < sizedirmenu; i++) + { + if (!strcmp(dirmenu[i]+DIR_STRING, tempname)) + { + dir_on[menudepthleft] = i; + break; + } + } + Z_Free(tempname); + } if (dir_on[menudepthleft] >= sizedirmenu) - dir_on[menudepthleft] = sizedirmenu; + dir_on[menudepthleft] = sizedirmenu-1; closedir(dirhandle); + + if (!sizedirmenu) + { + Z_Free(dirmenu); + return false; + } + return true; } #endif diff --git a/src/filesrch.h b/src/filesrch.h index 6bbabb9be..caa24f510 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -34,6 +34,9 @@ extern size_t menudepthleft; extern char **dirmenu; extern size_t sizedirmenu; extern size_t dir_on[menudepth]; +extern UINT8 refreshdirmenu; + +extern size_t packetsizetally; typedef enum { @@ -59,6 +62,22 @@ typedef enum */ } ext_enum; -boolean preparefilemenu(void); +typedef enum +{ + DIR_TYPE = 0, + DIR_LEN, + DIR_STRING +} dirname_enum; + +typedef enum +{ + REFRESHDIR_NORMAL = 1, + REFRESHDIR_ADDFILE = 2, + REFRESHDIR_WARNING = 4, + REFRESHDIR_ERROR = 8, + REFRESHDIR_MAX = 16 +} refreshdir_enum; + +boolean preparefilemenu(boolean samemenu); #endif // __FILESRCH_H__ diff --git a/src/m_menu.c b/src/m_menu.c index deda69616..a91f8b61a 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -482,11 +482,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum // --------- static menuitem_t MainMenu[] = { - {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76}, - {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84}, - {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92}, - {IT_CALL |IT_STRING, NULL, "options", M_Options, 100}, - {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, + {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84}, + {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92}, + {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100}, + {IT_CALL |IT_STRING, NULL, "options", M_Options, 108}, + //{IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108}, {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116}, }; @@ -1037,6 +1037,7 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70}, {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80}, + {IT_CALL | IT_STRING, NULL, "Add-ons...", M_Addons, 90}, }; static menuitem_t OP_ControlsMenu[] = @@ -4454,7 +4455,7 @@ static void M_Addons(INT32 choice) else --menupathindex[menudepthleft]; - if (!preparefilemenu()) + if (!preparefilemenu(false)) { M_StartMessage(M_GetText("No files/folders found.\n\n(Press a key)\n"),NULL,MM_NOTHING); return; @@ -4471,6 +4472,58 @@ static void M_DrawAddons(void) INT32 x, y; size_t i; + // hack - need to refresh at end of frame to handle addfile... + if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) + { + S_StartSound(NULL, sfx_lose); + M_SetupNextMenu(MISC_AddonsDef.prevMenu); + M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + return M_DrawMessageMenu(); + } + if (refreshdirmenu & REFRESHDIR_ADDFILE) + { + if (!(dirmenu[dir_on[menudepthleft]][DIR_TYPE] & EXT_LOADED)) + { + char *message = NULL; + S_StartSound(NULL, sfx_lose); + if (refreshdirmenu & REFRESHDIR_MAX) + message = va("\x82%s\x80\nMaximum number of add-ons reached.\nThis file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING); + else + message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING); + M_StartMessage(message,NULL,MM_NOTHING); + return M_DrawMessageMenu(); + } + + if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR)) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING); + return M_DrawMessageMenu(); + } + + S_StartSound(NULL, sfx_strpst); + } + +#define padding 16 +#define h (BASEVIDHEIGHT-(2*padding)) + x = FixedDiv((packetsizetally<>FRACBITS)); + x = padding + (FixedMul(h<>FRACBITS); + V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding, 1, h, 3); + V_DrawFill(BASEVIDWIDTH - padding, padding, 1, h, 3); + V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding-1, padding/4+2, 1, 3); + V_DrawFill(BASEVIDWIDTH - 5*padding/4 - 1, padding+h, padding/4+2, 1, 3); + for (y = h; y > 0; y--) + { + UINT8 colours[8] = {42, 40, 58, 65, 90, 97, 98, 113}; // when toast's coding it's british english hacker fucker + if (y < x) break; + V_DrawFill(BASEVIDWIDTH - 5*padding/4, y-1 + padding, padding/4, 1, colours[(8*(y-1))/h]); + } + if (y) + V_DrawFill(BASEVIDWIDTH - 5*padding/4, padding, padding/4, y, 27); +#undef padding +#undef h + // DRAW MENU x = currentMenu->x; y = currentMenu->y; @@ -4482,13 +4535,17 @@ static void M_DrawAddons(void) { UINT32 flags = 0; if (y > BASEVIDHEIGHT) break; + if (!dirmenu[i]) continue; // crash prevention - if ((dirmenu[i][0] & ~EXT_LOADED) != EXT_UP) + if ((dirmenu[i][DIR_TYPE] & ~EXT_LOADED) != EXT_UP) flags = V_ALLOWLOWERCASE; - if (dirmenu[i][0] & EXT_LOADED) + if (dirmenu[i][DIR_TYPE] & EXT_LOADED) flags |= V_TRANSLUCENT; - V_DrawString(x, y, flags, dirmenu[i]+2); + if (dirmenu[i][DIR_LEN] > 16) + V_DrawString(x, y, flags, va("%.13s...", dirmenu[i]+DIR_STRING)); + else + V_DrawString(x, y, flags, dirmenu[i]+DIR_STRING); y += SMALLLINEHEIGHT; } } @@ -4499,7 +4556,7 @@ static void M_AddonExec(INT32 ch) return; S_StartSound(NULL, sfx_strpst); - COM_ImmedExecute(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); + COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); } static void M_HandleAddons(INT32 choice) @@ -4521,66 +4578,65 @@ static void M_HandleAddons(INT32 choice) case KEY_ENTER: { boolean refresh = true; - switch (dirmenu[dir_on[menudepthleft]][0]) + if (!dirmenu[dir_on[menudepthleft]]) + S_StartSound(NULL, sfx_lose); + else { - case EXT_FOLDER: - if (menudepthleft) - { - strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2); - menupathindex[--menudepthleft] = strlen(menupath); - menupath[menupathindex[menudepthleft]] = 0; - - if (!preparefilemenu()) + switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE]) + { + case EXT_FOLDER: + if (menudepthleft) { - S_StartSound(NULL, sfx_skid); - M_StartMessage(va("%s\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); - menupath[menupathindex[++menudepthleft]] = 0; + strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING); + menupathindex[--menudepthleft] = strlen(menupath); + menupath[menupathindex[menudepthleft]] = 0; + + if (!preparefilemenu(false)) + { + S_StartSound(NULL, sfx_skid); + M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); + menupath[menupathindex[++menudepthleft]] = 0; + } + else + { + S_StartSound(NULL, sfx_strpst); + dir_on[menudepthleft] = 0; + refresh = false; + } } else { - S_StartSound(NULL, sfx_strpst); - dir_on[menudepthleft] = 0; - refresh = false; + S_StartSound(NULL, sfx_lose); + M_StartMessage(va("\x82%s%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); } - } - else - { + break; + case EXT_UP: + S_StartSound(NULL, sfx_skid); + menupath[menupathindex[++menudepthleft]] = 0; + break; + case EXT_TXT: + M_StartMessage(va("\x82%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO); + break; + case EXT_CFG: + M_AddonExec(KEY_ENTER); + break; + case EXT_LUA: +#ifndef HAVE_BLUA S_StartSound(NULL, sfx_lose); - M_StartMessage(va("%s%s\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING); - } - break; - case EXT_UP: - S_StartSound(NULL, sfx_skid); - menupath[menupathindex[++menudepthleft]] = 0; - break; - case EXT_TXT: - M_StartMessage(va("%s\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+2),M_AddonExec,MM_YESNO); - break; - case EXT_CFG: - M_AddonExec(KEY_ENTER); - break; - case EXT_LUA: -#ifdef HAVE_BLUA - S_StartSound(NULL, sfx_lose); - M_StartMessage(va("%s\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING); - break; + M_StartMessage(va("\x82%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); + break; #endif - // else intentional fallthrough - case EXT_WAD: - case EXT_SOC: - S_StartSound(NULL, sfx_strpst); - COM_ImmedExecute(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2)); - break; - default: - S_StartSound(NULL, sfx_lose); - } - if (refresh && !preparefilemenu()) - { - S_StartSound(NULL, sfx_lose); - M_SetupNextMenu(MISC_AddonsDef.prevMenu); - M_StartMessage(va("%s\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING); - return; + // else intentional fallthrough + case EXT_SOC: + case EXT_WAD: + COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING)); + break; + default: + S_StartSound(NULL, sfx_lose); + } } + if (refresh) + refreshdirmenu |= REFRESHDIR_NORMAL; } break; diff --git a/src/w_wad.c b/src/w_wad.c index b1b72eec1..1a6e7941a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -34,6 +34,8 @@ #include "z_zone.h" #include "fastcmp.h" +#include "filesrch.h" + #include "i_video.h" // rendermode #include "d_netfil.h" #include "dehacked.h" @@ -294,12 +296,11 @@ UINT16 W_LoadWadFile(const char *filename) UINT32 numlumps; size_t i; INT32 compressed = 0; - size_t packetsize = 0; - serverinfo_pak *dummycheck = NULL; + size_t packetsize; UINT8 md5sum[16]; - // Shut the compiler up. - (void)dummycheck; + if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) + refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier //CONS_Debug(DBG_SETUP, "Loading %s\n", filename); // @@ -308,6 +309,7 @@ UINT16 W_LoadWadFile(const char *filename) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; return INT16_MAX; } @@ -317,23 +319,22 @@ UINT16 W_LoadWadFile(const char *filename) // Check if wad files will overflow fileneededbuffer. Only the filename part // is send in the packet; cf. - for (i = 0; i < numwadfiles; i++) - { - packetsize += nameonlylength(wadfiles[i]->filename); - packetsize += 22; // MD5, etc. - } + packetsize = packetsizetally; packetsize += nameonlylength(filename); packetsize += 22; - if (packetsize > sizeof(dummycheck->fileneeded)) + if (packetsize > MAXFILENEEDED*sizeof(UINT8)) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); + refreshdirmenu |= REFRESHDIR_MAX; if (handle) fclose(handle); return INT16_MAX; } + packetsizetally = packetsize; + // detect dehacked file with the "soc" extension if (!stricmp(&filename[strlen(filename) - 4], ".soc")) {