diff --git a/src/d_clisrv.c b/src/d_clisrv.c index d66d5cb1e..e3d3bbef7 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -21,6 +21,7 @@ #include "i_system.h" #include "i_video.h" #include "d_net.h" +#include "d_netfil.h" // fileneedednum #include "d_main.h" #include "d_event.h" #include "g_game.h" @@ -1100,6 +1101,7 @@ typedef enum #endif CL_CONNECTED, CL_ABORTED, + CL_ASKFULLFILELIST, CL_ASKDOWNLOADFILES, CL_WAITDOWNLOADFILESRESPONSE, CL_CHALLENGE @@ -1110,6 +1112,7 @@ static void GetPackets(void); static cl_mode_t cl_mode = CL_SEARCHING; static boolean cl_needsdownload = false; +static UINT16 cl_lastcheckedfilecount = 0; static UINT8 cl_challengenum = 0; static UINT8 cl_challengequestion[MD5_LEN+1]; static char cl_challengepassword[65]; @@ -1227,6 +1230,9 @@ static inline void CL_DrawConnectionStatus(void) cltext = M_GetText("Waiting to download game state..."); break; #endif + case CL_ASKFULLFILELIST: + cltext = M_GetText("This server has a LOT of files!"); + break; case CL_ASKJOIN: case CL_WAITJOINRESPONSE: cltext = M_GetText("Requesting to join..."); @@ -1286,6 +1292,14 @@ static inline void CL_DrawConnectionStatus(void) } #endif +static boolean CL_AskFileList(INT32 firstfile) +{ + netbuffer->packettype = PT_TELLFILESNEEDED; + netbuffer->u.filesneedednum = firstfile; + + return HSendPacket(servernode, true, 0, sizeof (INT32)); +} + /** Sends a special packet to declare how many players in local * Used only in arbitratrenetstart() * Sends a PT_CLIENTJOIN packet to the server @@ -1404,7 +1418,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.actnum = 0; //mapheaderinfo[gamemap-1]->actnum - p = PutFileNeeded(); + p = PutFileNeeded(0); HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); } @@ -1875,6 +1889,66 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif // ifndef NONET +static boolean CL_FinishedFileList(void) +{ + INT32 i; + CONS_Printf(M_GetText("Checking files...\n")); + i = CL_CheckFiles(); + if (i == 3) // too many files + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have too many WAD files loaded\n" + "to add ones the server is using.\n" + "Please restart SRB2Kart before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 2) // cannot join for some reason + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have WAD files loaded or have\n" + "modified the game in some way, and\n" + "your file list does not match\n" + "the server's file list.\n" + "Please restart SRB2Kart before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 1) + cl_mode = CL_ASKJOIN; + else + { + // must download something + // can we, though? + if (!CL_CheckDownloadable()) // nope! + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You cannot connect to this server\n" + "because you cannot download the files\n" + "that you are missing from the server.\n\n" + "See the console or log file for\n" + "more details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + + cl_mode = CL_ASKDOWNLOADFILES; + } + return true; +} + /** Called by CL_ServerConnectionTicker * * \param viams ??? @@ -1918,66 +1992,16 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent) if (client) { - D_ParseFileneeded(serverlist[i].info.fileneedednum, - serverlist[i].info.fileneeded); - CONS_Printf(M_GetText("Checking files...\n")); - i = CL_CheckFiles(); - if (i == 3) // too many files + D_ParseFileneeded(serverlist[i].info.fileneedednum, serverlist[i].info.fileneeded, 0); + if (serverlist[i].info.kartvars & SV_LOTSOFADDONS) { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have too many WAD files loaded\n" - "to add ones the server is using.\n" - "Please restart SRB2Kart before connecting.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; + cl_mode = CL_ASKFULLFILELIST; + cl_lastcheckedfilecount = 0; + return true; } - else if (i == 2) // cannot join for some reason - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have WAD files loaded or have\n" - "modified the game in some way, and\n" - "your file list does not match\n" - "the server's file list.\n" - "Please restart SRB2Kart before connecting.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - else if (i == 1) - cl_mode = CL_ASKJOIN; - else - { - // must download something - // can we, though? - if (!CL_CheckDownloadable()) // nope! - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You cannot connect to this server\n" - "because you cannot download the files\n" - "that you are missing from the server.\n\n" - "See the console or log file for\n" - "more details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return false; - } - cl_mode = CL_ASKDOWNLOADFILES; - - // no problem if can't send packet, we will retry later - //if (CL_SendRequestFile()) - // cl_mode = CL_DOWNLOADFILES; - } + if (!CL_FinishedFileList()) + return false; } else cl_mode = CL_ASKJOIN; // files need not be checked for the server. @@ -2028,6 +2052,22 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic return false; break; + case CL_ASKFULLFILELIST: + if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved + { + if (!CL_FinishedFileList()) + return false; + } + else if (fileneedednum != cl_lastcheckedfilecount || *asksent + NEWTICRATE < I_GetTime()) + { + if (CL_AskFileList(fileneedednum)) + { + cl_lastcheckedfilecount = fileneedednum; + *asksent = I_GetTime(); + } + } + break; + case CL_DOWNLOADFILES: waitmore = false; for (i = 0; i < fileneedednum; i++) @@ -3891,6 +3931,39 @@ static void HandlePacketFromAwayNode(SINT8 node) #endif break; + case PT_TELLFILESNEEDED: + if (server && serverrunning) + { + UINT8 *p; + INT32 firstfile = netbuffer->u.filesneedednum; + + netbuffer->packettype = PT_MOREFILESNEEDED; + netbuffer->u.filesneededcfg.first = firstfile; + netbuffer->u.filesneededcfg.more = 0; + + p = PutFileNeeded(firstfile); + + HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); + } + else // Shouldn't get this if you aren't the server...? + Net_CloseConnection(node); + break; + + case PT_MOREFILESNEEDED: + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + SERVERONLY + if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum) + { + D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first); + if (!netbuffer->u.filesneededcfg.more) + cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list + } + break; + case PT_ASKINFO: if (server && serverrunning) { diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 44a3f17dd..e7879d582 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -93,6 +93,10 @@ typedef enum PT_NODETIMEOUT, // Packet sent to self if the connection times out. PT_RESYNCHING, // Packet sent to resync players. // Blocks game advance until synched. + + PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?" + PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)" + PT_PING, // Packet sent to tell clients the other client's latency to server. NUMPACKETTYPE } packettype_t; @@ -355,6 +359,7 @@ typedef struct } ATTRPACK joinchallenge_pak; #define SV_SPEEDMASK 0x03 +#define SV_LOTSOFADDONS 0x20 #define SV_DEDICATED 0x40 #define SV_PASSWORD 0x80 @@ -425,6 +430,14 @@ typedef struct UINT8 ctfteam; } ATTRPACK plrconfig; +typedef struct +{ + INT32 first; + UINT8 num; + UINT8 more; + UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) +} ATTRPACK filesneededconfig_pak; + // // Network packet data // @@ -457,6 +470,8 @@ typedef struct msaskinfo_pak msaskinfo; // 22 bytes plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) + INT32 filesneedednum; // 4 bytes + filesneededconfig_pak filesneededcfg; // ??? bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; diff --git a/src/d_main.c b/src/d_main.c index f6eefc9bc..08ae8af17 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -74,7 +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, mainwadstally +#include "filesrch.h" // refreshdirmenu #ifdef CMAKECONFIG #include "config.h" @@ -1233,8 +1233,6 @@ void D_SRB2Main(void) #endif //ifndef DEVELOP - mainwadstally = packetsizetally; - // // search for maps // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index a49e7a973..31a5b0239 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4298,14 +4298,6 @@ static void Command_Addfile(void) if (*p == '\\' || *p == '/' || *p == ':') break; ++p; - // check total packet size and no of files currently loaded - // See W_LoadWadFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8))) - { - CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - return; - } WRITESTRINGN(buf_p,p,240); @@ -4420,8 +4412,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) } // See W_LoadWadFile in w_wad.c - if ((numwadfiles >= MAX_WADFILES) - || ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8))) + if (numwadfiles >= MAX_WADFILES) toomany = true; else ncs = findfile(filename,md5sum,true); diff --git a/src/d_netfil.c b/src/d_netfil.c index 99a058403..4dcd3da4a 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -107,19 +107,39 @@ INT32 lastfilenum = -1; * Used to have size limiting built in - now handed via W_LoadWadFile in w_wad.c * */ -UINT8 *PutFileNeeded(void) +UINT8 *PutFileNeeded(UINT16 firstfile) { - size_t i, count = 0; - UINT8 *p = netbuffer->u.serverinfo.fileneeded; + size_t i; + UINT8 count = 0; + UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded; + UINT8 *p = p_start; char wadfilename[MAX_WADPATH] = ""; UINT8 filestatus; - for (i = 0; i < numwadfiles; i++) + for (i = mainwads; i < numwadfiles; i++) { // If it has only music/sound lumps, don't put it in the list if (!wadfiles[i]->important) continue; + if (firstfile) + { // Skip files until we reach the first file. + firstfile--; + continue; + } + + nameonly(strcpy(wadfilename, wadfiles[i]->filename)); + + if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED) + { + // Too many files to send all at once + if (netbuffer->packettype == PT_MOREFILESNEEDED) + netbuffer->u.filesneededcfg.more = 1; + else + netbuffer->u.serverinfo.kartvars |= SV_LOTSOFADDONS; + break; + } + filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS // Store in the upper four bits @@ -134,30 +154,32 @@ UINT8 *PutFileNeeded(void) count++; WRITEUINT32(p, wadfiles[i]->filesize); - nameonly(strcpy(wadfilename, wadfiles[i]->filename)); WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITEMEM(p, wadfiles[i]->md5sum, 16); } - netbuffer->u.serverinfo.fileneedednum = (UINT8)count; + if (netbuffer->packettype == PT_MOREFILESNEEDED) + netbuffer->u.filesneededcfg.num = count; + else + netbuffer->u.serverinfo.fileneedednum = count; return p; } /** Parses the serverinfo packet and fills the fileneeded table on client * - * \param fileneedednum_parm The number of files needed to join the server + * \param fileneedednum_parm The number of files (sent in this page) needed to join the server * \param fileneededstr The memory block containing the list of needed files - * + * \param firstfile The first file index to read from */ -void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) +void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile) { INT32 i; UINT8 *p; UINT8 filestatus; - fileneedednum = fileneedednum_parm; + fileneedednum = firstfile + fileneedednum_parm; p = (UINT8 *)fileneededstr; - for (i = 0; i < fileneedednum; i++) + for (i = firstfile; i < fileneedednum; i++) { fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet filestatus = READUINT8(p); // The first byte is the file status @@ -338,7 +360,8 @@ INT32 CL_CheckFiles(void) // the first is the iwad (the main wad file) // we don't care if it's called srb2.srb or srb2.wad. // Never download the IWAD, just assume it's there and identical - fileneeded[0].status = FS_OPEN; + // ...No! Why were we sending the base wads to begin with?? + //fileneeded[0].status = FS_OPEN; // Modified game handling -- check for an identical file list // must be identical in files loaded AND in order @@ -346,7 +369,7 @@ INT32 CL_CheckFiles(void) if (modifiedgame) { CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); - for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) + for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;) { if (j < numwadfiles && !wadfiles[j]->important) { @@ -373,15 +396,12 @@ INT32 CL_CheckFiles(void) return 1; } - // See W_LoadWadFile in w_wad.c - packetsize = packetsizetally; - - for (i = 1; i < fileneedednum; i++) + for (i = 0; i < fileneedednum; i++) { CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); // Check in already loaded files - for (j = 1; wadfiles[j]; j++) + for (j = mainwads; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); if (!stricmp(wadfilename, fileneeded[i].filename) && @@ -397,8 +417,7 @@ INT32 CL_CheckFiles(void) packetsize += nameonlylength(fileneeded[i].filename) + 22; - if ((numwadfiles+filestoget >= MAX_WADFILES) - || (packetsize > MAXFILENEEDED*sizeof(UINT8))) + if (mainwads+filestoget >= MAX_WADFILES) return 3; filestoget++; diff --git a/src/d_netfil.h b/src/d_netfil.h index 3d7c2ed59..2f0333311 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -53,8 +53,8 @@ extern char downloaddir[512]; extern INT32 lastfilenum; #endif -UINT8 *PutFileNeeded(void); -void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr); +UINT8 *PutFileNeeded(UINT16 firstfile); +void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile); void CL_PrepareDownloadSaveGame(const char *tmpsave); INT32 CL_CheckFiles(void); diff --git a/src/filesrch.c b/src/filesrch.c index 6827dc57e..d132e9fb4 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -341,8 +341,6 @@ size_t dir_on[menudepth]; UINT8 refreshdirmenu = 0; char *refreshdirname = NULL; -size_t packetsizetally = 0; -size_t mainwadstally = 0; #if defined (_XBOX) && defined (_MSC_VER) filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, diff --git a/src/filesrch.h b/src/filesrch.h index dbcc5fc37..4cb92b238 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -42,9 +42,6 @@ extern size_t dir_on[menudepth]; extern UINT8 refreshdirmenu; extern char *refreshdirname; -extern size_t packetsizetally; -extern size_t mainwadstally; - typedef enum { EXT_FOLDER = 0, diff --git a/src/m_menu.c b/src/m_menu.c index 0f7e285b6..a345da599 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4816,10 +4816,7 @@ static void M_DrawAddons(void) y = FRACUNIT; else { - x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< y) - y = x; + y = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))< FRACUNIT) // happens because of how we're shrinkin' it a little y = FRACUNIT; } diff --git a/src/w_wad.c b/src/w_wad.c index 915701840..da82a276d 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -652,7 +652,6 @@ UINT16 W_InitFile(const char *filename) restype_t type; UINT16 numlumps = 0; size_t i; - size_t packetsize; UINT8 md5sum[16]; boolean important; @@ -684,24 +683,7 @@ UINT16 W_InitFile(const char *filename) if ((handle = W_OpenWadFile(&filename, true)) == NULL) return INT16_MAX; - // Check if wad files will overflow fileneededbuffer. Only the filename part - // is send in the packet; cf. - // see PutFileNeeded in d_netfil.c - if ((important = !W_VerifyNMUSlumps(filename))) - { - packetsize = packetsizetally + nameonlylength(filename) + 22; - - 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; - } + important = !W_VerifyNMUSlumps(filename); #ifndef NOMD5 //