// // denis - D_AddSearchDir // Split a new directory string using the separator and append results to the output // void D_AddSearchDir(std::vector<std::string> &dirs, const char *dir, const char separator) { if(!dir) return; // search through dwd std::stringstream ss(dir); std::string segment; while(!ss.eof()) { std::getline(ss, segment, separator); if(!segment.length()) continue; FixPathSeparator(segment); I_ExpandHomeDir(segment); if(segment[segment.length() - 1] != PATHSEPCHAR) segment += PATHSEP; dirs.push_back(segment); } }
// // M_AppendExtension // // Add an extension onto the end of a filename, returns false if it failed. // if_needed detects if an extension is not present in path, if it isn't, it is // added. // The extension must contain a . at the beginning BOOL M_AppendExtension (std::string &filename, std::string extension, bool if_needed) { FixPathSeparator(filename); size_t l = filename.find_last_of(PATHSEPCHAR); if(l == filename.length()) return false; size_t dot = extension.find_first_of('.'); if (dot == std::string::npos) return false; if (if_needed) { size_t dot = filename.find_last_of('.'); if (dot == std::string::npos) filename.append(extension); return true; } filename.append(extension); return true; }
// // M_AppendExtension // // Add an extension onto the end of a filename, returns false if it failed. // if_needed detects if an extension is not present in path, if it isn't, it is // added. // The extension must contain a . at the beginning BOOL M_AppendExtension (std::string &path, std::string extension, bool if_needed) { FixPathSeparator(path); size_t l = path.find_last_of('/'); if(l == path.length()) return false; size_t dot = extension.find_first_of('.'); if (dot == std::string::npos) return false; if (if_needed) { size_t pathdot = path.find_last_of('.'); if (pathdot == std::string::npos) path.append(extension); return true; } path.append(extension); return true; }
std::string I_GetBinaryDir() { std::string ret; #ifdef _XBOX // D:\ always corresponds to the binary path whether running from DVD or HDD. ret = "D:\\"; #elif defined GEKKO ret = "sd:/"; #elif defined WIN32 char tmp[MAX_PATH]; // denis - todo - make separate function GetModuleFileName (NULL, tmp, sizeof(tmp)); ret = tmp; #else if(!Args[0]) return "./"; char realp[PATH_MAX]; if(realpath(Args[0], realp)) ret = realp; else { // search through $PATH const char *path = getenv("PATH"); if(path) { std::stringstream ss(path); std::string segment; while(ss) { std::getline(ss, segment, ':'); if(!segment.length()) continue; if(segment[segment.length() - 1] != PATHSEPCHAR) segment += PATHSEP; segment += Args[0]; if(realpath(segment.c_str(), realp)) { ret = realp; break; } } } } #endif FixPathSeparator(ret); size_t slash = ret.find_last_of(PATHSEPCHAR); if(slash == std::string::npos) return ""; else return ret.substr(0, slash); }
std::string I_GetUserFileName (const char *file) { #if defined(UNIX) && !defined(GEKKO) // return absolute or explicitly relative pathnames unmodified, // so launchers or CLI/console users have control over netdemo placement if (file && (file[0] == PATHSEPCHAR || // /path/to/file (file[0] == '.' && file[1] == PATHSEPCHAR) || // ./file (file[0] == '.' && file[1] == '.' && file[2] == PATHSEPCHAR))) // ../file return std::string (file); std::string path = I_GetHomeDir(); if(path[path.length() - 1] != PATHSEPCHAR) path += PATHSEP; path += ".odamex"; struct stat info; if (stat (path.c_str(), &info) == -1) { if (mkdir (path.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == -1) { I_FatalError ("Failed to create %s directory:\n%s", path.c_str(), strerror (errno)); } } else { if (!S_ISDIR(info.st_mode)) { I_FatalError ("%s must be a directory", path.c_str()); } } path += PATHSEP; path += file; #elif defined(_XBOX) std::string path = "T:"; path += PATHSEP; path += file; #else if (!PathIsRelative(file)) return std::string (file); std::string path = I_GetBinaryDir(); if(path[path.length() - 1] != PATHSEPCHAR) path += PATHSEP; path += file; #endif FixPathSeparator(path); return path; }
// // M_ExtractFilePath // // Extract the path from a filename that includes one void M_ExtractFilePath (std::string path, std::string &dest) { FixPathSeparator(path); size_t l = path.find_last_of('/'); if(l == std::string::npos) l = path.length(); if(l < path.length()) dest = path.substr(0, l); }
// // M_ExtractFilePath // // Extract the path from a filename that includes one void M_ExtractFilePath (std::string filename, std::string &dest) { FixPathSeparator(filename); size_t l = filename.find_last_of(PATHSEPCHAR); if(l == std::string::npos) l = filename.length(); if(l < filename.length()) dest = filename.substr(0, l); }
std::string I_GetBinaryDir() { std::string ret; #ifdef WIN32 char tmp[MAX_PATH]; // denis - todo - make separate function GetModuleFileName (NULL, tmp, sizeof(tmp)); ret = tmp; #else if(!Args[0]) return "./"; char realp[PATH_MAX]; if(realpath(Args[0], realp)) ret = realp; else { // search through $PATH const char *path = getenv("PATH"); if(path) { std::stringstream ss(path); std::string segment; while(ss) { std::getline(ss, segment, ':'); if(!segment.length()) continue; if(segment[segment.length() - 1] != '/') segment += "/"; segment += Args[0]; if(realpath(segment.c_str(), realp)) { ret = realp; break; } } } } #endif FixPathSeparator(ret); size_t slash = ret.find_last_of('/'); if(slash == std::string::npos) return ""; else return ret.substr(0, slash); }
std::string I_GetCWD() { char tmp[4096] = {0}; std::string ret = "./"; const char *cwd = getcwd(tmp, sizeof(tmp)); if(cwd) ret = cwd; FixPathSeparator(ret); return ret; }
// // M_ExtractFileName // // Extract the name of a file from a path (name = filename with extension) void M_ExtractFileName (std::string filename, std::string &dest) { FixPathSeparator(filename); size_t l = filename.find_last_of('/'); if(l == std::string::npos) l = 0; else l++; if(l < filename.length()) dest = filename.substr(l, filename.length()); }
std::string I_GetUserFileName (const char *file) { #if defined(UNIX) && !defined(GEKKO) std::string path = I_GetHomeDir(); if(path[path.length() - 1] != PATHSEPCHAR) path += PATHSEP; path += ".odamex"; struct stat info; if (stat (path.c_str(), &info) == -1) { if (mkdir (path.c_str(), S_IRUSR | S_IWUSR | S_IXUSR) == -1) { I_FatalError ("Failed to create %s directory:\n%s", path.c_str(), strerror (errno)); } } else { if (!S_ISDIR(info.st_mode)) { I_FatalError ("%s must be a directory", path.c_str()); } } path += PATHSEP; path += file; #elif defined(_XBOX) std::string path = "T:"; path += PATHSEP; path += file; #else std::string path = I_GetBinaryDir(); if(path[path.length() - 1] != PATHSEPCHAR) path += PATHSEP; path += file; #endif FixPathSeparator(path); return path; }
// // M_ExtractFileBase // // Extract the base file name from a path string (basefile = filename with no extension) // // e.g. /asdf/qwerty.zxc -> qwerty // iuyt.wad -> iuyt // hgfd -> hgfd // // Note: On windows, text after the last . is considered the extension, so any preceding // .'s won't be removed void M_ExtractFileBase (std::string path, std::string &dest) { FixPathSeparator(path); size_t l = path.find_last_of('/'); if(l == std::string::npos) l = 0; else l++; size_t e = path.find_last_of('.'); if(e == std::string::npos) e = path.length(); if(l < path.length()) dest = path.substr(l, e); }
// // M_ExtractFileBase // // Extract the base file name from a path string (basefile = filename with no extension) // // e.g. /asdf/qwerty.zxc -> qwerty // iuyt.wad -> iuyt // hgfd -> hgfd // // Note: On windows, text after the last . is considered the extension, so any preceding // .'s won't be removed void M_ExtractFileBase (std::string filename, std::string &dest) { FixPathSeparator(filename); size_t l = filename.find_last_of(PATHSEPCHAR); if(l == std::string::npos) l = 0; else l++; size_t e = filename.find_last_of('.'); if(e == std::string::npos) e = filename.length(); if(l < filename.length()) dest = filename.substr(l, e - l); }
// // D_CleanseFileName // // Strips a file name of path information and transforms it into uppercase // std::string D_CleanseFileName(const std::string &filename, const std::string &ext) { std::string newname(filename); FixPathSeparator(newname); if (ext.length()) M_AppendExtension(newname, "." + ext); size_t slash = newname.find_last_of(PATHSEPCHAR); if (slash != std::string::npos) newname = newname.substr(slash + 1, newname.length() - slash); std::transform(newname.begin(), newname.end(), newname.begin(), toupper); return newname; }
void SV_InitMultipleFiles (std::vector<std::string> filenames) { wadnames.clear(); for(size_t i = 0; i < filenames.size(); i++) { FixPathSeparator (filenames[i]); std::string name = filenames[i]; M_AppendExtension (filenames[i], ".wad"); size_t slash = name.find_last_of(PATHSEPCHAR); if(slash != std::string::npos) name = name.substr(slash + 1, name.length() - slash); std::transform(name.begin(), name.end(), name.begin(), toupper); wadnames.push_back(name); } }
std::string W_AddFile (std::string filename) { wadinfo_t header; lumpinfo_t* lump_p; size_t i; FILE *handle; size_t length; size_t startlump; size_t res; filelump_t* fileinfo; filelump_t singleinfo; FixPathSeparator (filename); std::string name = filename; M_AppendExtension (name, ".wad"); // open the file if ( (handle = fopen (filename.c_str(), "rb")) == NULL) { Printf (PRINT_HIGH, " couldn't open %s\n", filename.c_str()); return ""; } Printf (PRINT_HIGH, "adding %s\n", filename.c_str()); startlump = numlumps; res = fread (&header, sizeof(header), 1, handle); header.identification = LELONG(header.identification); if (header.identification != IWAD_ID && header.identification != PWAD_ID) { // raw lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = M_FileLength(handle); M_ExtractFileBase (filename, name); numlumps++; Printf (PRINT_HIGH, " (single lump)\n", header.numlumps); } else { // WAD file header.numlumps = LELONG(header.numlumps); header.infotableofs = LELONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); if(length > (unsigned)M_FileLength(handle)) { Printf (PRINT_HIGH, " bad number of lumps for %s\n", filename.c_str()); fclose(handle); return ""; } fileinfo = (filelump_t *)Z_Malloc (length, PU_STATIC, 0); fseek (handle, header.infotableofs, SEEK_SET); res = fread (fileinfo, length, 1, handle); numlumps += header.numlumps; Printf (PRINT_HIGH, " (%d lumps)\n", header.numlumps); } // Fill in lumpinfo lumpinfo = (lumpinfo_t *)Realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); if (!lumpinfo) I_Error ("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++) { lump_p->handle = handle; lump_p->position = LELONG(fileinfo->filepos); lump_p->size = LELONG(fileinfo->size); strncpy (lump_p->name, fileinfo->name, 8); // W_CheckNumForName needs all lump names in upper case std::transform(lump_p->name, lump_p->name+8, lump_p->name, toupper); } return W_MD5(filename); }
void NetDemo::writeLauncherSequence(buf_t *netbuffer) { cvar_t *var = NULL, *prev_cvar = NULL; // Server sends launcher info MSG_WriteLong (netbuffer, CHALLENGE); MSG_WriteLong (netbuffer, 0); // server_token // get sv_hostname and write it var = cvar_t::FindCVar("sv_hostname", &prev_cvar); MSG_WriteString (netbuffer, server_host.c_str()); int playersingame = 0; for (size_t i = 0; i < players.size(); i++) { if (players[i].ingame()) playersingame++; } MSG_WriteByte (netbuffer, playersingame); MSG_WriteByte (netbuffer, 0); // sv_maxclients MSG_WriteString (netbuffer, level.mapname); // names of all the wadfiles on the server size_t numwads = wadfiles.size(); if (numwads > 0xff) numwads = 0xff; MSG_WriteByte (netbuffer, numwads - 1); for (size_t n = 1; n < numwads; n++) { std::string tmpname = wadfiles[n]; // strip absolute paths, as they present a security risk FixPathSeparator(tmpname); size_t slash = tmpname.find_last_of(PATHSEPCHAR); if (slash != std::string::npos) tmpname = tmpname.substr(slash + 1, tmpname.length() - slash); MSG_WriteString (netbuffer, tmpname.c_str()); } MSG_WriteBool (netbuffer, 0); // deathmatch? MSG_WriteByte (netbuffer, 0); // sv_skill MSG_WriteBool (netbuffer, (sv_gametype == GM_TEAMDM)); MSG_WriteBool (netbuffer, (sv_gametype == GM_CTF)); for (size_t i = 0; i < players.size(); i++) { // Notes: client just ignores this data but still expects to parse it if (players[i].ingame()) { MSG_WriteString (netbuffer, ""); // player's netname MSG_WriteShort (netbuffer, 0); // player's fragcount MSG_WriteLong (netbuffer, 0); // player's ping MSG_WriteByte (netbuffer, 0); // player's team } } // MD5 hash sums for all the wadfiles on the server for (size_t n = 1; n < numwads; n++) MSG_WriteString (netbuffer, wadhashes[n].c_str()); MSG_WriteString (netbuffer, ""); // sv_website.cstring() if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF) { MSG_WriteLong (netbuffer, 0); // sv_scorelimit for (size_t n = 0; n < NUMTEAMS; n++) { MSG_WriteBool (netbuffer, false); } } MSG_WriteShort (netbuffer, VERSION); // Note: these are ignored by clients when the client connects anyway // so they don't need real data MSG_WriteString (netbuffer, ""); // sv_email.cstring() MSG_WriteShort (netbuffer, 0); // sv_timelimit MSG_WriteShort (netbuffer, 0); // timeleft before end of level MSG_WriteShort (netbuffer, 0); // sv_fraglimit MSG_WriteBool (netbuffer, false); // sv_itemrespawn MSG_WriteBool (netbuffer, false); // sv_weaponstay MSG_WriteBool (netbuffer, false); // sv_friendlyfire MSG_WriteBool (netbuffer, false); // sv_allowexit MSG_WriteBool (netbuffer, false); // sv_infiniteammo MSG_WriteBool (netbuffer, false); // sv_nomonsters MSG_WriteBool (netbuffer, false); // sv_monstersrespawn MSG_WriteBool (netbuffer, false); // sv_fastmonsters MSG_WriteBool (netbuffer, false); // sv_allowjump MSG_WriteBool (netbuffer, false); // sv_freelook MSG_WriteBool (netbuffer, false); // sv_waddownload MSG_WriteBool (netbuffer, false); // sv_emptyreset MSG_WriteBool (netbuffer, false); // sv_cleanmaps MSG_WriteBool (netbuffer, false); // sv_fragexitswitch for (size_t i = 0; i < players.size(); i++) { if (players[i].ingame()) { MSG_WriteShort (netbuffer, players[i].killcount); MSG_WriteShort (netbuffer, players[i].deathcount); int timeingame = (time(NULL) - players[i].JoinTime)/60; if (timeingame < 0) timeingame = 0; MSG_WriteShort (netbuffer, timeingame); } } MSG_WriteLong(netbuffer, (DWORD)0x01020304); MSG_WriteShort(netbuffer, sv_maxplayers); for (size_t i = 0; i < players.size(); i++) { if (players[i].ingame()) MSG_WriteBool (netbuffer, players[i].spectator); } MSG_WriteLong (netbuffer, (DWORD)0x01020305); MSG_WriteShort (netbuffer, 0); // join_passowrd MSG_WriteLong (netbuffer, GAMEVER); // TODO: handle patch files MSG_WriteByte (netbuffer, 0); // patchfiles.size() // MSG_WriteByte (netbuffer, patchfiles.size()); // for (size_t n = 0; n < patchfiles.size(); n++) // MSG_WriteString(netbuffer, patchfiles[n].c_str()); }
void D_DoomMain (void) { M_ClearRandom(); gamestate = GS_STARTUP; if (lzo_init () != LZO_E_OK) // [RH] Initialize the minilzo package. I_FatalError ("Could not initialize LZO routines"); C_ExecCmdLineParams (false, true); // [Nes] test for +logfile command I_Init (); D_CheckNetGame (); M_LoadDefaults (); // load before initing other systems M_FindResponseFile(); // [ML] 23/1/07 - Add Response file support back in C_ExecCmdLineParams (true, false); // [RH] do all +set commands on the command line //D_AddDefWads(); //SV_InitMultipleFiles (wadfiles); //wadhashes = W_InitMultipleFiles (wadfiles); // Base systems have been inited; enable cvar callbacks cvar_t::EnableCallbacks (); // [RH] Initialize configurable strings. D_InitStrings (); // [RH] User-configurable startup strings. Because BOOM does. if (STARTUP1[0]) Printf (PRINT_HIGH, "%s\n", STARTUP1); if (STARTUP2[0]) Printf (PRINT_HIGH, "%s\n", STARTUP2); if (STARTUP3[0]) Printf (PRINT_HIGH, "%s\n", STARTUP3); if (STARTUP4[0]) Printf (PRINT_HIGH, "%s\n", STARTUP4); if (STARTUP5[0]) Printf (PRINT_HIGH, "%s\n", STARTUP5); devparm = Args.CheckParm ("-devparm"); // get skill / episode / map from parms strcpy (startmap, (gameinfo.flags & GI_MAPxx) ? "MAP01" : "E1M1"); const char *val = Args.CheckValue ("-skill"); if (val) { skill.Set (val[0]-'0'); } unsigned p = Args.CheckParm ("-warp"); if (p && p < Args.NumArgs() - (1+(gameinfo.flags & GI_MAPxx ? 0 : 1))) { int ep, map; if (gameinfo.flags & GI_MAPxx) { ep = 1; map = atoi (Args.GetArg(p+1)); } else { ep = Args.GetArg(p+1)[0]-'0'; map = Args.GetArg(p+2)[0]-'0'; } strncpy (startmap, CalcMapName (ep, map), 8); autostart = true; } // [RH] Hack to handle +map p = Args.CheckParm ("+map"); if (p && p < Args.NumArgs()-1) { strncpy (startmap, Args.GetArg (p+1), 8); ((char *)Args.GetArg (p))[0] = '-'; autostart = true; } if (devparm) Printf (PRINT_HIGH, "%s", Strings[0].builtin); // D_DEVSTR const char *v = Args.CheckValue ("-timer"); if (v) { double time = atof (v); Printf (PRINT_HIGH, "Levels will end after %g minute%s.\n", time, time > 1 ? "s" : ""); timelimit.Set ((float)time); } const char *w = Args.CheckValue ("-avg"); if (w) { Printf (PRINT_HIGH, "Austin Virtual Gaming: Levels will end after 20 minutes\n"); timelimit.Set (20); } // Check for -file in shareware if (modifiedgame && (gameinfo.flags & GI_SHAREWARE)) I_FatalError ("You cannot -file with the shareware version. Register!"); // [RH] Initialize items. Still only used for the give command. :-( InitItems (); // [RH] Lock any cvars that should be locked now that we're // about to begin the game. cvar_t::EnableNoSet (); Printf(PRINT_HIGH, "========== Odamex Server Initialized ==========\n"); #ifdef UNIX if (Args.CheckParm("-background")) daemon_init(); #endif // Use wads mentioned on the commandline to start with std::vector<std::string> start_wads; std::string custwad; const char *iwadparm = Args.CheckValue ("-iwad"); if (iwadparm) { custwad = iwadparm; FixPathSeparator (custwad); start_wads.push_back(custwad); } DArgs files = Args.GatherFiles ("-file", ".wad", true); if (files.NumArgs() > 0) { modifiedgame = true; for (size_t i = 0; i < files.NumArgs(); i++) { start_wads.push_back(files.GetArg (i)); } } D_DoomWadReboot(start_wads); // [RH] Now that all game subsystems have been initialized, // do all commands on the command line other than +set C_ExecCmdLineParams (false, false); strncpy(level.mapname, startmap, sizeof(level.mapname)); gamestate = GS_STARTUP; G_ChangeMap (); D_DoomLoop (); // never returns }
// // W_AddFile // // All files are optional, but at least one file must be found // (PWAD, if all required lumps are present). // Files with a .wad extension are wadlink files with multiple lumps. // Other files are single lumps with the base filename for the lump name. // // Map reloads are supported through WAD reload so no need for vanilla tilde // reload hack here // std::string W_AddFile(std::string filename) { FILE* handle; filelump_t* fileinfo; FixPathSeparator(filename); if ( (handle = fopen(filename.c_str(), "rb")) == NULL) { Printf(PRINT_HIGH, "couldn't open %s\n", filename.c_str()); return ""; } Printf(PRINT_HIGH, "adding %s", filename.c_str()); size_t newlumps; wadinfo_t header; fread(&header, sizeof(header), 1, handle); header.identification = LELONG(header.identification); if (header.identification != IWAD_ID && header.identification != PWAD_ID) { // raw lump file std::string lumpname; M_ExtractFileBase(filename, lumpname); fileinfo = new filelump_t[1]; fileinfo->filepos = 0; fileinfo->size = M_FileLength(handle); std::transform(lumpname.c_str(), lumpname.c_str() + 8, fileinfo->name, toupper); newlumps = 1; Printf(PRINT_HIGH, " (single lump)\n"); } else { // WAD file header.numlumps = LELONG(header.numlumps); header.infotableofs = LELONG(header.infotableofs); size_t length = header.numlumps * sizeof(filelump_t); if (length > (unsigned)M_FileLength(handle)) { Printf(PRINT_HIGH, "\nbad number of lumps for %s\n", filename.c_str()); fclose(handle); return ""; } fileinfo = new filelump_t[header.numlumps]; fseek(handle, header.infotableofs, SEEK_SET); fread(fileinfo, length, 1, handle); // convert from little-endian to target arch and capitalize lump name for (int i = 0; i < header.numlumps; i++) { fileinfo[i].filepos = LELONG(fileinfo[i].filepos); fileinfo[i].size = LELONG(fileinfo[i].size); std::transform(fileinfo[i].name, fileinfo[i].name + 8, fileinfo[i].name, toupper); } newlumps = header.numlumps; Printf(PRINT_HIGH, " (%d lumps)\n", header.numlumps); } W_AddLumps(handle, fileinfo, newlumps, false); delete [] fileinfo; return W_MD5(filename); }
std::vector<size_t> D_DoomWadReboot( const std::vector<std::string> &wadnames, const std::vector<std::string> &patch_files, std::vector<std::string> needhashes ) { std::vector<size_t> fails; size_t i; // already loaded these? if (lastWadRebootSuccess && !wadhashes.empty() && needhashes == std::vector<std::string>(wadhashes.begin()+1, wadhashes.end())) { // fast track if files have not been changed // denis - todo - actually check the file timestamps Printf (PRINT_HIGH, "Currently loaded WADs match server checksum\n\n"); return std::vector<size_t>(); } // assume failure lastWadRebootSuccess = false; if (modifiedgame && (gameinfo.flags & GI_SHAREWARE)) I_Error ("\nYou cannot switch WAD with the shareware version. Register!"); if(gamestate == GS_LEVEL) G_ExitLevel(0, 0); AM_Stop(); S_Stop(); DThinker::DestroyAllThinkers(); // Close all open WAD files W_Close(); // [ML] 9/11/10: Reset custom wad level information from MAPINFO et al. // I have never used memset, I hope I am not invoking satan by doing this :( if (wadlevelinfos) { for (i = 0; i < numwadlevelinfos; i++) if (wadlevelinfos[i].snapshot) { delete wadlevelinfos[i].snapshot; wadlevelinfos[i].snapshot = NULL; } memset(wadlevelinfos,0,sizeof(wadlevelinfos)); numwadlevelinfos = 0; } if (wadclusterinfos) { memset(wadclusterinfos,0,sizeof(wadclusterinfos)); numwadclusterinfos = 0; } // Restart the memory manager Z_Init(); gamestate_t oldgamestate = gamestate; gamestate = GS_STARTUP; // prevent console from trying to use nonexistant font wadfiles.clear(); modifiedgame = false; std::string custwad; if(wadnames.empty() == false) custwad = wadnames[0]; D_AddDefWads(custwad); for(i = 0; i < wadnames.size(); i++) { std::string tmp = wadnames[i]; // strip absolute paths, as they present a security risk FixPathSeparator(tmp); size_t slash = tmp.find_last_of(PATHSEPCHAR); if(slash != std::string::npos) tmp = tmp.substr(slash + 1, tmp.length() - slash); // [Russell] - Generate a hash if it doesn't exist already if (needhashes[i].empty()) needhashes[i] = W_MD5(tmp); std::string file = BaseFileSearch(tmp, ".wad", needhashes[i]); if(file.length()) wadfiles.push_back(file); else { Printf (PRINT_HIGH, "could not find WAD: %s\n", tmp.c_str()); fails.push_back(i); } } if(wadnames.size() > 1) modifiedgame = true; wadhashes = W_InitMultipleFiles (wadfiles); UndoDehPatch(); // [RH] Initialize localizable strings. GStrings.ResetStrings (); GStrings.Compact (); D_DoDefDehackedPatch(patch_files); //gotconback = false; //C_InitConsole(DisplayWidth, DisplayHeight, true); HU_Init (); if(!(DefaultPalette = InitPalettes("PLAYPAL"))) I_Error("Could not reinitialize palette"); V_InitPalette(); G_SetLevelStrings (); G_ParseMapInfo (); G_ParseMusInfo (); S_ParseSndInfo(); M_Init(); R_Init(); P_InitEffects(); // [ML] Do this here so we don't have to put particle crap in server P_Init(); S_Init (snd_sfxvolume, snd_musicvolume); ST_Init(); // preserve state lastWadRebootSuccess = fails.empty(); gamestate = oldgamestate; // GS_STARTUP would prevent netcode connecting properly return fails; }