* 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.
This commit is contained in:
toasterbabe 2017-04-29 16:40:07 +01:00
parent da003d61c3
commit 66f56bbba3
7 changed files with 201 additions and 84 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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__

View File

@ -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), (MAXFILENEEDED*sizeof(UINT8)<<FRACBITS));
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-8, V_TRANSLUCENT, va("%d%%", (100*x)>>FRACBITS));
x = padding + (FixedMul(h<<FRACBITS, FRACUNIT - x)>>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;

View File

@ -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"))
{