diff options
Diffstat (limited to 'source/sv_save.c')
-rw-r--r-- | source/sv_save.c | 327 |
1 files changed, 0 insertions, 327 deletions
diff --git a/source/sv_save.c b/source/sv_save.c deleted file mode 100644 index 7b4f36f..0000000 --- a/source/sv_save.c +++ /dev/null @@ -1,327 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "sv_local.h" - - -/* -=============================================================================== - -SAVEGAME FILES - -=============================================================================== -*/ - -static void write_binary_file( const char *name ) { - qerror_t ret; - - ret = FS_WriteFile( name, msg_write.data, msg_write.cursize ); - if( ret < 0 ) { - Com_EPrintf( "%s: couldn't write %s: %s\n", __func__, name, Q_ErrorString( ret ) ); - } -} - -static void write_server_file( qboolean autosave ) { - char name[MAX_OSPATH]; - cvar_t *var; - - // write the comment field - MSG_WriteByte( autosave ); - MSG_WriteLong( time( NULL ) ); - MSG_WriteString( sv.configstrings[CS_NAME] ); - - // write the mapcmd - MSG_WriteString( sv.name ); - - // write all CVAR_LATCH cvars - // these will be things like coop, skill, deathmatch, etc - for( var = cvar_vars; var; var = var->next ) { - if (!(var->flags & CVAR_LATCH)) - continue; - MSG_WriteString( var->name ); - MSG_WriteString( var->string ); - } - MSG_WriteString( NULL ); - - Q_snprintf (name, sizeof(name), "save/current/server.state"); - write_binary_file( name ); - - SZ_Clear( &msg_write ); - - // write game state - Q_snprintf (name, sizeof(name), "%s/save/current/game.state", fs_gamedir); - ge->WriteGame (name, autosave); -} - -static void write_level_file( void ) { - char name[MAX_OSPATH]; - int i; - char *s; - size_t len; - byte portalbits[MAX_MAP_PORTAL_BYTES]; - - Com_DPrintf( "%s()\n", __func__ ); - - // write configstrings - for( i = 0; i < MAX_CONFIGSTRINGS; i++ ) { - s = sv.configstrings[i]; - if( !s[0] ) { - continue; - } - len = strlen( s ); - if( len > MAX_QPATH ) { - len = MAX_QPATH; - } - - MSG_WriteShort( i ); - MSG_WriteData( s, len ); - MSG_WriteByte( 0 ); - } - MSG_WriteShort( MAX_CONFIGSTRINGS ); - - len = CM_WritePortalBits( &sv.cm, portalbits ); - MSG_WriteByte( len ); - MSG_WriteData( portalbits, len ); - - Q_snprintf (name, sizeof(name), "save/current/server.level"); - write_binary_file( name ); - - SZ_Clear( &msg_write ); - - Q_snprintf( name, sizeof( name ), "%s/save/current/game.level", fs_gamedir ); - ge->WriteLevel( name ); -} - - -static void read_binary_file( const char *name ) { - qhandle_t f; - ssize_t len; - - len = FS_FOpenFile( name, &f, FS_MODE_READ|FS_TYPE_REAL|FS_PATH_GAME ); - if( !f ) { - Com_Error( ERR_DROP, "%s: couldn't open %s: %s\n", __func__, name, Q_ErrorString( len ) ); - } - - if( len > MAX_MSGLEN ) { - FS_FCloseFile( f ); - Com_Error( ERR_DROP, "%s: %s is too large\n", __func__, name ); - } - - FS_Read( msg_read_buffer, len, f ); - - SZ_Init( &msg_read, msg_read_buffer, len ); - msg_read.cursize = len; - msg_read.allowunderflow = qfalse; - - FS_FCloseFile( f ); -} - -static void read_server_file( void ) { - char name[MAX_OSPATH], string[MAX_STRING_CHARS]; - char mapcmd[MAX_TOKEN_CHARS]; - - Com_DPrintf( "%s()\n", __func__ ); - - Q_snprintf (name, sizeof(name), "save/current/server.state"); - read_binary_file( name ); - - // read the comment field - MSG_ReadByte(); - MSG_ReadLong(); - MSG_ReadString( NULL, 0 ); - - // read the mapcmd - MSG_ReadString( mapcmd, sizeof( mapcmd ) ); - - // read all CVAR_LATCH cvars - // these will be things like coop, skill, deathmatch, etc - while( 1 ) { - MSG_ReadString( name, MAX_QPATH ); - if( !name[0] ) - break; - MSG_ReadString( string, sizeof( string ) ); - Cvar_Set( name, string ); - } - - // start a new game fresh with new cvars - SV_InitGame( qfalse ); - - // error out immediately if game doesn't support safe savegames - if( !( g_features->integer & GMF_ENHANCED_SAVEGAMES ) ) { - Com_Error( ERR_DROP, "Game does not support enhanced savegames" ); - } - - // read game state - Q_snprintf (name, sizeof(name), "%s/save/current/game.state", fs_gamedir); - ge->ReadGame (name); - - // go to the map - sv.state = ss_game; // don't save current level when changing - SV_Map( mapcmd, qfalse ); -} - -static void read_level_file( void ) { - char name[MAX_OSPATH]; - size_t len; - int index; - - Com_DPrintf( "%s\n", __func__ ); - - Q_snprintf (name, sizeof(name), "save/current/server.level"); - read_binary_file( name ); - - while( 1 ) { - index = MSG_ReadShort(); - if( index == MAX_CONFIGSTRINGS ) { - break; - } - if( index < 0 || index >= MAX_CONFIGSTRINGS ) { - Com_Error( ERR_DROP, "%s: bad configstring index", __func__ ); - } - MSG_ReadString( sv.configstrings[index], MAX_QPATH ); - } - - len = MSG_ReadByte(); - if( len > MAX_MAP_PORTAL_BYTES ) { - Com_Error( ERR_DROP, "%s: bad portalbits length", __func__ ); - } - - SV_ClearWorld(); - - CM_SetPortalStates( &sv.cm, MSG_ReadData( len ), len ); - - Q_snprintf( name, sizeof( name ), "%s/save/current/game.level", fs_gamedir ); - ge->ReadLevel( name ); - - ge->RunFrame(); - ge->RunFrame(); -} - - -/* -============== -SV_Loadgame_f - -============== -*/ -void SV_Loadgame_f (void) { - char name[MAX_OSPATH]; - char *dir; - - if (Cmd_Argc() != 2) { - Com_Printf ("Usage: %s <directory>\n", Cmd_Argv(0)); - return; - } - - if( dedicated->integer ) { - Com_Printf ("Savegames are for listen servers only\n"); - return; - } - - dir = Cmd_Argv(1); - if (strstr (dir, "..") || strchr (dir, '/') || strchr (dir, '\\') ) { - Com_Printf ("Bad savedir.\n"); - return; - } - - // make sure the server.ssv file exists - Q_snprintf (name, sizeof(name), "save/%s/server.state", Cmd_Argv(1)); - if (!FS_FileExists( name ) ) { - Com_Printf ("No such savegame: %s\n", name); - return; - } - - Com_Printf ("Loading game...\n"); - - //SV_CopySaveGame (Cmd_Argv(1), "current"); - - read_server_file(); - - read_level_file(); -} - - -/* -============== -SV_Savegame_f - -============== -*/ -void SV_Savegame_f( void ) { - char *dir; - - if (sv.state != ss_game) { - Com_Printf ("You must be in a game to save.\n"); - return; - } - - if (Cmd_Argc() != 2) { - Com_Printf ("Usage: %s <directory>\n", Cmd_Argv(0)); - return; - } - - if( dedicated->integer ) { - Com_Printf ("Savegames are for listen servers only\n"); - return; - } - - // don't bother saving if we can't read them back! - if( !( g_features->integer & GMF_ENHANCED_SAVEGAMES ) ) { - Com_Printf ("Game does not support enhanced savegames\n"); - return; - } - - if (Cvar_VariableInteger("deathmatch")) { - Com_Printf ("Can't savegame in a deathmatch\n"); - return; - } - - if (sv_maxclients->integer == 1 && svs.udp_client_pool[0].edict->client->ps.stats[STAT_HEALTH] <= 0) { - Com_Printf ("Can't savegame while dead!\n"); - return; - } - - dir = Cmd_Argv(1); - if (strstr (dir, "..") || strchr (dir, '/') || strchr (dir, '\\') ) { - Com_Printf ("Bad savedir.\n"); - return; - } - - if (!strcmp (dir, "current")) { - Com_Printf ("Can't save to 'current'\n"); - return; - } - - Com_Printf ("Saving game...\n"); - - // archive current level, including all client edicts. - // when the level is reloaded, they will be shells awaiting - // a connecting client - write_level_file(); - - // save server state - write_server_file( qfalse ); - - // copy it off - //SV_CopySaveGame ("current", dir); - - Com_Printf ("Done.\n"); -} - |