diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1387c80e4..f35428c95 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -533,6 +533,7 @@ typedef enum CL_DOWNLOADFILES, CL_ASKJOIN, CL_LOADFILES, + CL_SETUPFILES, CL_WAITJOINRESPONSE, CL_DOWNLOADSAVEGAME, CL_CONNECTED, @@ -617,6 +618,9 @@ static inline void CL_DrawConnectionStatus(void) case CL_CONFIRMCONNECT: cltext = ""; break; + case CL_SETUPFILES: + cltext = M_GetText("Configuring addons..."); + break; case CL_ASKJOIN: case CL_WAITJOINRESPONSE: if (serverisfull) @@ -1851,7 +1855,12 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic cl_mode = CL_LOADFILES; break; case CL_LOADFILES: - if (CL_LoadServerFiles()) + if (CL_LoadServerFiles()) + cl_mode = CL_SETUPFILES; + + break; + case CL_SETUPFILES: + if (P_PartialAddGetStage() < 0 || P_MultiSetupWadFiles(false)) { *asksent = 0; //This ensure the first join ask is right away firstconnectattempttime = I_GetTime(); @@ -2079,7 +2088,12 @@ static void CL_ConnectToServer(void) { // If the connection was aborted for some reason, leave if (!CL_ServerConnectionTicker(tmpsave, &oldtic, &asksent)) + { + if (P_PartialAddGetStage() >= 0) + P_MultiSetupWadFiles(true); // in case any partial adds were done + return; + } if (server) { diff --git a/src/d_main.c b/src/d_main.c index 7fb82482e..947350a08 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1203,8 +1203,6 @@ void D_SRB2Main(void) { INT32 i, p; - INT32 numbasemapheaders; - INT32 pstartmap = 1; boolean autostart = false; @@ -1461,9 +1459,7 @@ void D_SRB2Main(void) // // search for mainwad maps // - P_InitMapData(0); - - numbasemapheaders = nummapheaders; + P_InitMapData(false); CON_SetLoadingProgress(LOADED_IWAD); @@ -1474,7 +1470,7 @@ void D_SRB2Main(void) // // search for pwad maps // - P_InitMapData(numbasemapheaders); + P_InitMapData(true); CON_SetLoadingProgress(LOADED_PWAD); diff --git a/src/d_netfil.c b/src/d_netfil.c index 3de3a0030..ffd2c546b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -552,7 +552,7 @@ boolean CL_LoadServerFiles(void) continue; // Already loaded else if (fileneeded[i].status == FS_FOUND) { - P_AddWadFile(fileneeded[i].filename); + P_PartialAddWadFile(fileneeded[i].filename); G_SetGameModified(true, false); fileneeded[i].status = FS_OPEN; return false; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 63d093ae1..d33a88daf 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -326,22 +326,30 @@ patch_t *HU_UpdateOrBlankPatch(patch_t **user, boolean required, const char *for va_list ap; char buffer[9]; - lumpnum_t lump; + lumpnum_t lump = INT16_MAX; patch_t *patch; va_start (ap, format); vsnprintf(buffer, sizeof buffer, format, ap); va_end (ap); - if (user && p_adding_file != INT16_MAX) + if (user && partadd_earliestfile != UINT16_MAX) { - lump = W_CheckNumForNamePwad(buffer, p_adding_file, 0); + UINT16 fileref = numwadfiles; + lump = INT16_MAX; + + while ((lump == INT16_MAX) && ((--fileref) >= partadd_earliestfile)) + { + lump = W_CheckNumForNamePwad(buffer, fileref, 0); + } /* no update in this wad */ - if (lump == INT16_MAX) + if (fileref < partadd_earliestfile) return *user; - lump |= (p_adding_file << 16); + CONS_Printf("pe = %d, fr = %d\n", partadd_earliestfile, fileref); + + lump |= (fileref << 16); } else { diff --git a/src/p_setup.c b/src/p_setup.c index 3de23a0d1..b08e75f01 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -170,6 +170,13 @@ mapthing_t *playerstarts[MAXPLAYERS]; mapthing_t *bluectfstarts[MAXPLAYERS]; mapthing_t *redctfstarts[MAXPLAYERS]; +// Global state for PartialAddWadFile/MultiSetupWadFiles +// Might be replacable with parameters, but non-trivial when the functions are called on separate tics +static SINT8 partadd_stage = -1; +static boolean partadd_important = false; +UINT16 partadd_earliestfile = UINT16_MAX; + + // Maintain *ZOOM TUBE* waypoints // Renamed because SRB2Kart owns real waypoints. mobj_t *tubewaypoints[NUMTUBEWAYPOINTSEQUENCES][TUBEWAYPOINTSEQUENCESIZE]; @@ -7745,7 +7752,7 @@ lumpnum_t wadnamelump = LUMPERROR; INT16 wadnamemap = 0; // gamemap based // Initialising map data (and catching replacements)... -UINT8 P_InitMapData(INT32 numexistingmapheaders) +UINT8 P_InitMapData(boolean existingmapheaders) { UINT8 ret = 0; INT32 i; @@ -7763,7 +7770,7 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders) if (maplump == INT16_MAX) { #ifndef DEVELOP - if (!numexistingmapheaders) + if (!existingmapheaders) { I_Error("P_InitMapData: Base map %s has a header but no level\n", name); } @@ -7816,7 +7823,7 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders) ret |= MAPRET_ADDED; CONS_Printf("%s\n", name); - if (numexistingmapheaders && mapheaderinfo[i]->lumpnum != LUMPERROR) + if (existingmapheaders && mapheaderinfo[i]->lumpnum != LUMPERROR) { G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you @@ -7866,23 +7873,32 @@ UINT8 P_InitMapData(INT32 numexistingmapheaders) return ret; } -UINT16 p_adding_file = INT16_MAX; - // // Add a wadfile to the active wad files, // replace sounds, musics, patches, textures, sprites and maps // boolean P_AddWadFile(const char *wadfilename) +{ + UINT16 wadnum; + + if ((wadnum = P_PartialAddWadFile(wadfilename)) == UINT16_MAX) + return false; + + P_MultiSetupWadFiles(true); + return true; +} + +// +// Add a WAD file and do the per-WAD setup stages. +// Call P_MultiSetupWadFiles as soon as possible after any number of these. +// +UINT16 P_PartialAddWadFile(const char *wadfilename) { size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0; - INT32 numexistingmapheaders = nummapheaders; UINT16 numlumps, wadnum; char *name; lumpinfo_t *lumpinfo; - //boolean texturechange = false; ///\todo Useless; broken when back-frontporting PK3 changes? - UINT8 mapsadded = 0; - // Vars to help us with the position start and amount of each resource type. // Useful for PK3s since they use folders. // WADs use markers for some resources, but others such as sounds are checked lump-by-lump anyway. @@ -7902,10 +7918,19 @@ boolean P_AddWadFile(const char *wadfilename) refreshdirmenu |= REFRESHDIR_NOTLOADED; return false; } - else - wadnum = (UINT16)(numwadfiles-1); - p_adding_file = wadnum; + wadnum = (UINT16)(numwadfiles-1); + + // Init partadd. + if (wadfiles[wadnum]->important) + { + partadd_important = true; + } + if (partadd_stage != 0) + { + partadd_earliestfile = wadnum; + } + partadd_stage = 0; switch(wadfiles[wadnum]->type) { @@ -7939,8 +7964,6 @@ boolean P_AddWadFile(const char *wadfilename) // R_LoadSpritsRange(wadnum, sprPos, sprNum); // if (texNum) // Textures. TODO: R_LoadTextures() does the folder positioning once again. New function maybe? // R_LoadTextures(); -// if (mapNum) // Maps. TODO: Actually implement the map WAD loading code, lulz. -// P_LoadWadMapRange(wadnum, mapPos, mapNum); break; default: lumpinfo = wadfiles[wadnum]->lumpinfo; @@ -8005,23 +8028,14 @@ boolean P_AddWadFile(const char *wadfilename) // TEXTURES/etc. list. R_LoadTexturesPwad(wadnum); // numtexture changes - // Reload ANIMDEFS - P_InitPicAnims(); - // Reload BRIGHT K_InitBrightmapsPwad(wadnum); - // Flush and reload HUD graphics - //ST_UnloadGraphics(); - HU_LoadGraphics(); - ST_LoadGraphics(); - // // look for skins // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] R_PatchSkins(wadnum); // toast: PATCH PATCH - ST_ReloadSkinFaceGraphics(); // // edit music defs @@ -8029,37 +8043,99 @@ boolean P_AddWadFile(const char *wadfilename) S_LoadMusicDefs(wadnum); // - // search for maps + // extra sprite/skin data // - mapsadded = P_InitMapData(numexistingmapheaders); - - if (!mapsadded) - CONS_Printf(M_GetText("No maps added\n")); - R_LoadSpriteInfoLumps(wadnum, numlumps); -#ifdef HWRENDER - HWR_ReloadModels(); -#endif + // For anything that has to be done over every wadfile at once, see P_MultiSetupWadFiles. - // reload status bar (warning should have valid player!) - if (gamestate == GS_LEVEL) - ST_Start(); - - // Prevent savefile cheating - if (cursaveslot > 0) - cursaveslot = 0; - - if ((mapsadded & MAPRET_CURRENTREPLACED) && gamestate == GS_LEVEL && (netgame || multiplayer)) - { - CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap); - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); - } - - refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_GAMEDATA to disappear the next frame, but it's a bit too dangerous for that... - - p_adding_file = INT16_MAX; + refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_ flags to disappear the next frame, but this one's a bit too dangerous for that... return true; } + +// Only exists to make sure there's no way to overwrite partadd_stage externally +// unless you really push yourself. +SINT8 P_PartialAddGetStage(void) +{ + return partadd_stage; +} + +// +// Set up a series of partially added WAD files. +// Setup functions that iterate over every loaded WAD go here. +// If fullsetup false, only do one stage per call. +// +boolean P_MultiSetupWadFiles(boolean fullsetup) +{ + if (partadd_stage < 0) + I_Error(M_GetText("P_MultiSetupWadFiles: Post-load addon setup attempted without loading any addons first")); + + if (partadd_stage == 0) + { + // Flush and reload HUD graphics + //ST_UnloadGraphics(); + HU_LoadGraphics(); + ST_LoadGraphics(); + ST_ReloadSkinFaceGraphics(); + + if (!partadd_important) + partadd_stage = -1; // everything done + else if (fullsetup) + partadd_stage++; + } + + if (partadd_stage == 1) + { + // Prevent savefile cheating + if (cursaveslot >= 0) + cursaveslot = 0; + + // Reload ANIMATED / ANIMDEFS + P_InitPicAnims(); + + // reload status bar (warning should have valid player!) + if (gamestate == GS_LEVEL) + ST_Start(); + +#ifdef HWRENDER + HWR_ReloadModels(); +#endif + + if (fullsetup) + partadd_stage++; + } + + if (partadd_stage == 2) + { + UINT8 mapsadded = P_InitMapData(true); + + if (!mapsadded) + CONS_Printf(M_GetText("No maps added\n")); + + if ((mapsadded & MAPRET_CURRENTREPLACED) + && (gamestate == GS_LEVEL) + && (netgame || multiplayer)) + { + CONS_Printf(M_GetText("Current map %d replaced by added file, ending the level to ensure consistency.\n"), gamemap); + if (server) + SendNetXCmd(XD_EXITLEVEL, NULL, 0); + } + + //if (fullsetup) + //partadd_stage++; + partadd_stage = -1; + } + + I_Assert(!fullsetup || partadd_stage < 0); + + if (partadd_stage < 0) + { + partadd_important = false; + partadd_earliestfile = UINT16_MAX; + return true; + } + + partadd_stage++; + return false; +} diff --git a/src/p_setup.h b/src/p_setup.h index d5d3aa7d0..04a3233e0 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -96,8 +96,6 @@ INT32 P_CheckLevelFlat(const char *flatname); extern size_t nummapthings; extern mapthing_t *mapthings; -extern UINT16 p_adding_file; - void P_SetupLevelSky(const char *skytexname, boolean global); void P_RespawnThings(void); boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate); @@ -108,11 +106,29 @@ boolean P_AddWadFile(const char *wadfilename); #define MAPRET_ADDED (1) #define MAPRET_CURRENTREPLACED (1<<1) -UINT8 P_InitMapData(INT32 numexistingmapheaders); +UINT8 P_InitMapData(boolean existingmapheaders); extern lumpnum_t wadnamelump; extern INT16 wadnamemap; #define WADNAMECHECK(name) (!strncmp(name, "WADNAME", 7)) +// WARNING: The following functions should be grouped as follows: +// any amount of PartialAdds followed by MultiSetups until returned true, +// as soon as possible. +UINT16 P_PartialAddWadFile(const char *wadfilename); +// Run a single stage of multisetup, or all of them if fullsetup set. +// fullsetup true: run everything +// otherwise multiple stages +// returns true if setup finished on this call, false otherwise (always true on fullsetup) +// throws I_Error if called without any partial adds started as a safeguard +boolean P_MultiSetupWadFiles(boolean fullsetup); +// Get the current setup stage. +// if negative, no PartialAdds done since last MultiSetup +// if 0, partial adds done but MultiSetup not called yet +// if positive, setup's partway done +SINT8 P_PartialAddGetStage(void); +extern UINT16 partadd_earliestfile; + + boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); diff --git a/src/p_spec.c b/src/p_spec.c index 91b958e31..31af5b0e6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -148,7 +148,7 @@ static void GrowAnimDefs(void) // A prototype; here instead of p_spec.h, so they're "private" void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); -void P_ParseAnimationDefintion(SINT8 istexture); +void P_ParseAnimationDefintion(void); /** Sets up texture and flat animations. * @@ -161,8 +161,6 @@ void P_ParseAnimationDefintion(SINT8 istexture); * \author Steven McGranahan (original), Shadow Hog (had to rewrite it to handle multiple WADs), JTE (had to rewrite it to handle multiple WADs _correctly_) */ -static boolean animdeftempflats = false; // only until ANIMDEFS flats are removed - void P_InitPicAnims(void) { // Init animation @@ -182,7 +180,6 @@ void P_InitPicAnims(void) while (animdefsLumpNum != INT16_MAX) { - animdeftempflats = ((p_adding_file == INT16_MAX) || p_adding_file == w); P_ParseANIMDEFSLump(w, animdefsLumpNum); animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); } @@ -204,31 +201,14 @@ void P_InitPicAnims(void) lastanim = anims; for (i = 0; animdefs[i].istexture != -1; i++) { - if (animdefs[i].istexture == 1) - { - if (R_CheckTextureNumForName(animdefs[i].startname) == -1) - continue; - - lastanim->picnum = R_TextureNumForName(animdefs[i].endname); - lastanim->basepic = R_TextureNumForName(animdefs[i].startname); - } - else - { - if (animdefs[i].istexture == 2) - { - CONS_Alert(CONS_WARNING, "ANIMDEFS flats are disabled; flat support in general will be removed soon! (%s, %s)\n", animdefs[i].startname, animdefs[i].endname); - } + if (animdefs[i].istexture != 1) continue; - } -#if 0 - { - if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) - continue; - lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); - lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); - } -#endif + if (R_CheckTextureNumForName(animdefs[i].startname) == -1) + continue; + + lastanim->picnum = R_TextureNumForName(animdefs[i].endname); + lastanim->basepic = R_TextureNumForName(animdefs[i].startname); lastanim->istexture = animdefs[i].istexture; lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; @@ -285,21 +265,20 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) if (stricmp(animdefsToken, "TEXTURE") == 0) { Z_Free(animdefsToken); - P_ParseAnimationDefintion(1); + P_ParseAnimationDefintion(); } else if (stricmp(animdefsToken, "FLAT") == 0) { - Z_Free(animdefsToken); - P_ParseAnimationDefintion(0); + I_Error("Error parsing ANIMDEFS lump: FLats are no longer supported by Ring Racers"); } else if (stricmp(animdefsToken, "OSCILLATE") == 0) { // This probably came off the tail of an earlier definition. It's technically legal syntax, but we don't support it. - I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by SRB2"); + I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"OSCILLATE\" (the animation plays in reverse when it reaches the end) are not supported by Ring Racers"); } else { - I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\" or \"FLAT\", got \"%s\"",animdefsToken); + I_Error("Error parsing ANIMDEFS lump: Expected \"TEXTURE\", got \"%s\"",animdefsToken); } // parse next line while (*p != '\0' && *p != '\n') ++p; @@ -310,7 +289,7 @@ void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum) Z_Free((void *)animdefsText); } -void P_ParseAnimationDefintion(SINT8 istexture) +void P_ParseAnimationDefintion(void) { char *animdefsToken; size_t animdefsTokenLength; @@ -353,8 +332,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) // Search for existing animdef for (i = 0; i < maxanims; i++) - if (animdefs[i].istexture == istexture // Check if it's the same type! - && stricmp(animdefsToken, animdefs[i].startname) == 0) + if (stricmp(animdefsToken, animdefs[i].startname) == 0) { //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); @@ -376,10 +354,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) Z_Free(animdefsToken); // set texture type - if (istexture) - animdefs[i].istexture = 1; - else - animdefs[i].istexture = (animdeftempflats ? 2 : 0); + animdefs[i].istexture = 1; // "RANGE" animdefsToken = M_GetToken(NULL); @@ -457,16 +432,6 @@ void P_ParseAnimationDefintion(SINT8 istexture) } animdefs[i].speed = animSpeed; Z_Free(animdefsToken); - -#ifdef WALLFLATS - // hehe... uhh..... - if (!istexture) - { - GrowAnimDefs(); - M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t)); - animdefs[maxanims-1].istexture = 1; - } -#endif } /** Checks for flats in levelflats that are part of a flat animation sequence