2010-11-25 16:36:27 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* =======================================================================
|
|
|
|
*
|
|
|
|
* Serverside savegame code.
|
|
|
|
*
|
|
|
|
* =======================================================================
|
2012-04-29 13:57:33 +00:00
|
|
|
*/
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
#include "header/server.h"
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
void CM_ReadPortalState(fileHandle_t f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete save/<XXX>/
|
|
|
|
*/
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_WipeSavegame(char *savename)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
char name[MAX_OSPATH];
|
|
|
|
char *s;
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("SV_WipeSaveGame(%s)\n", savename);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/server.ssv",
|
|
|
|
FS_Gamedir(), savename);
|
|
|
|
|
|
|
|
remove(name);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/game.ssv",
|
|
|
|
FS_Gamedir(), savename);
|
|
|
|
|
|
|
|
remove(name);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), savename);
|
|
|
|
s = Sys_FindFirst(name, 0, 0);
|
|
|
|
|
|
|
|
while (s)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
remove(s);
|
|
|
|
s = Sys_FindNext(0, 0);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Sys_FindClose();
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/*.sv2", FS_Gamedir(), savename);
|
|
|
|
s = Sys_FindFirst(name, 0, 0);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
while (s)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
remove(s);
|
|
|
|
s = Sys_FindNext(0, 0);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Sys_FindClose();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
CopyFile(char *src, char *dst)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
FILE *f1, *f2;
|
2010-11-25 16:36:27 +00:00
|
|
|
size_t l;
|
2012-07-21 08:06:07 +00:00
|
|
|
byte buffer[65536];
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("CopyFile (%s, %s)\n", src, dst);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
f1 = fopen(src, "rb");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f1)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
f2 = fopen(dst, "wb");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f2)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
fclose(f1);
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
while (1)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
l = fread(buffer, 1, sizeof(buffer), f1);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!l)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
fwrite(buffer, 1, l, f2);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
fclose(f1);
|
|
|
|
fclose(f2);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_CopySaveGame(char *src, char *dst)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
char name[MAX_OSPATH], name2[MAX_OSPATH];
|
2010-11-25 16:36:27 +00:00
|
|
|
size_t l, len;
|
2012-07-21 08:06:07 +00:00
|
|
|
char *found;
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("SV_CopySaveGame(%s, %s)\n", src, dst);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_WipeSavegame(dst);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* copy the savegame over */
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), src);
|
|
|
|
Com_sprintf(name2, sizeof(name2), "%s/save/%s/server.ssv", FS_Gamedir(), dst);
|
|
|
|
FS_CreatePath(name2);
|
|
|
|
CopyFile(name, name2);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir(), src);
|
|
|
|
Com_sprintf(name2, sizeof(name2), "%s/save/%s/game.ssv", FS_Gamedir(), dst);
|
|
|
|
CopyFile(name, name2);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/", FS_Gamedir(), src);
|
|
|
|
len = strlen(name);
|
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), src);
|
|
|
|
found = Sys_FindFirst(name, 0, 0);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
while (found)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
strcpy(name + len, found + len);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name2, sizeof(name2), "%s/save/%s/%s",
|
|
|
|
FS_Gamedir(), dst, found + len);
|
|
|
|
CopyFile(name, name2);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* change sav to sv2 */
|
2012-07-21 08:06:07 +00:00
|
|
|
l = strlen(name);
|
|
|
|
strcpy(name + l - 3, "sv2");
|
|
|
|
l = strlen(name2);
|
|
|
|
strcpy(name2 + l - 3, "sv2");
|
|
|
|
CopyFile(name, name2);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
found = Sys_FindNext(0, 0);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Sys_FindClose();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_WriteLevelFile(void)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
char name[MAX_OSPATH];
|
|
|
|
FILE *f;
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("SV_WriteLevelFile()\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/current/%s.sv2",
|
|
|
|
FS_Gamedir(), sv.name);
|
|
|
|
f = fopen(name, "wb");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Failed to open %s\n", name);
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
fwrite(sv.configstrings, sizeof(sv.configstrings), 1, f);
|
|
|
|
CM_WritePortalState(f);
|
|
|
|
fclose(f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/current/%s.sav",
|
|
|
|
FS_Gamedir(), sv.name);
|
|
|
|
ge->WriteLevel(name);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_ReadLevelFile(void)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
char name[MAX_OSPATH];
|
2010-11-25 16:36:27 +00:00
|
|
|
fileHandle_t f;
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("SV_ReadLevelFile()\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "save/current/%s.sv2", sv.name);
|
|
|
|
FS_FOpenFile(name, &f, FS_READ);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Failed to open %s\n", name);
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
FS_Read(sv.configstrings, sizeof(sv.configstrings), f);
|
|
|
|
CM_ReadPortalState(f);
|
|
|
|
FS_FCloseFile(f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/current/%s.sav",
|
|
|
|
FS_Gamedir(), sv.name);
|
|
|
|
ge->ReadLevel(name);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_WriteServerFile(qboolean autosave)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
FILE *f;
|
|
|
|
cvar_t *var;
|
|
|
|
char name[MAX_OSPATH], string[128];
|
|
|
|
char comment[32];
|
2010-11-25 16:36:27 +00:00
|
|
|
time_t aclock;
|
2012-07-21 08:06:07 +00:00
|
|
|
struct tm *newtime;
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("SV_WriteServerFile(%s)\n", autosave ? "true" : "false");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/current/server.ssv", FS_Gamedir());
|
|
|
|
f = fopen(name, "wb");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Couldn't write %s\n", name);
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write the comment field */
|
2012-07-21 08:06:07 +00:00
|
|
|
memset(comment, 0, sizeof(comment));
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!autosave)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
time(&aclock);
|
|
|
|
newtime = localtime(&aclock);
|
|
|
|
Com_sprintf(comment, sizeof(comment), "%2i:%i%i %2i/%2i ",
|
|
|
|
newtime->tm_hour, newtime->tm_min / 10,
|
|
|
|
newtime->tm_min % 10, newtime->tm_mon + 1,
|
|
|
|
newtime->tm_mday);
|
2013-05-11 11:24:13 +00:00
|
|
|
Q_strlcat(comment, sv.configstrings[CS_NAME], sizeof(comment));
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* autosaved */
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(comment, sizeof(comment), "ENTERING %s",
|
|
|
|
sv.configstrings[CS_NAME]);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
fwrite(comment, 1, sizeof(comment), f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* write the mapcmd */
|
2012-07-21 08:06:07 +00:00
|
|
|
fwrite(svs.mapcmd, 1, sizeof(svs.mapcmd), f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-04-29 13:57:33 +00:00
|
|
|
/* write all CVAR_LATCH cvars
|
2012-07-21 08:06:07 +00:00
|
|
|
these will be things like coop,
|
|
|
|
skill, deathmatch, etc */
|
|
|
|
for (var = cvar_vars; var; var = var->next)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!(var->flags & CVAR_LATCH))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if ((strlen(var->name) >= sizeof(name) - 1) ||
|
|
|
|
(strlen(var->string) >= sizeof(string) - 1))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Cvar too long: %s = %s\n", var->name, var->string);
|
2010-11-25 16:36:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
memset(name, 0, sizeof(name));
|
|
|
|
memset(string, 0, sizeof(string));
|
|
|
|
strcpy(name, var->name);
|
|
|
|
strcpy(string, var->string);
|
|
|
|
fwrite(name, 1, sizeof(name), f);
|
|
|
|
fwrite(string, 1, sizeof(string), f);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
fclose(f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* write game state */
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir());
|
|
|
|
ge->WriteGame(name, autosave);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_ReadServerFile(void)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
|
|
|
fileHandle_t f;
|
2012-07-21 08:06:07 +00:00
|
|
|
char name[MAX_OSPATH], string[128];
|
|
|
|
char comment[32];
|
|
|
|
char mapcmd[MAX_TOKEN_CHARS];
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_DPrintf("SV_ReadServerFile()\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "save/current/server.ssv");
|
|
|
|
FS_FOpenFile(name, &f, FS_READ);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Couldn't read %s\n", name);
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read the comment field */
|
2012-07-21 08:06:07 +00:00
|
|
|
FS_Read(comment, sizeof(comment), f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* read the mapcmd */
|
2012-07-21 08:06:07 +00:00
|
|
|
FS_Read(mapcmd, sizeof(mapcmd), f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-04-29 13:57:33 +00:00
|
|
|
/* read all CVAR_LATCH cvars
|
2012-07-21 08:06:07 +00:00
|
|
|
these will be things like
|
|
|
|
coop, skill, deathmatch, etc */
|
|
|
|
while (1)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!FS_FRead(name, 1, sizeof(name), f))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
FS_Read(string, sizeof(string), f);
|
|
|
|
Com_DPrintf("Set %s = %s\n", name, string);
|
|
|
|
Cvar_ForceSet(name, string);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
FS_FCloseFile(f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* start a new game fresh with new cvars */
|
|
|
|
SV_InitGame();
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
strcpy(svs.mapcmd, mapcmd);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* read game state */
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/current/game.ssv", FS_Gamedir());
|
|
|
|
ge->ReadGame(name);
|
2012-04-29 13:57:33 +00:00
|
|
|
}
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_Loadgame_f(void)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
char name[MAX_OSPATH];
|
|
|
|
FILE *f;
|
|
|
|
char *dir;
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (Cmd_Argc() != 2)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("USAGE: loadgame <directory>\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Loading game...\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
dir = Cmd_Argv(1);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (strstr(dir, "..") || strstr(dir, "/") || strstr(dir, "\\"))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Bad savedir.\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* make sure the server.ssv file exists */
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_sprintf(name, sizeof(name), "%s/save/%s/server.ssv",
|
|
|
|
FS_Gamedir(), Cmd_Argv(1));
|
|
|
|
f = fopen(name, "rb");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!f)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("No such savegame: %s\n", name);
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
fclose(f);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_CopySaveGame(Cmd_Argv(1), "current");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
SV_ReadServerFile();
|
|
|
|
|
|
|
|
/* go to the map */
|
|
|
|
sv.state = ss_dead; /* don't save current level when changing */
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_Map(false, svs.mapcmd, true);
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_Savegame_f(void)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
char *dir;
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (sv.state != ss_game)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("You must be in a game to save.\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (Cmd_Argc() != 2)
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("USAGE: savegame <directory>\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (Cvar_VariableValue("deathmatch"))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Can't savegame in a deathmatch\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (!strcmp(Cmd_Argv(1), "current"))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Can't save to 'current'\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if ((maxclients->value == 1) &&
|
|
|
|
(svs.clients[0].edict->client->ps.stats[STAT_HEALTH] <= 0))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("\nCan't savegame while dead!\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
dir = Cmd_Argv(1);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
if (strstr(dir, "..") || strstr(dir, "/") || strstr(dir, "\\"))
|
2010-11-25 16:36:27 +00:00
|
|
|
{
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Bad savedir.\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Saving game...\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-04-29 13:57:33 +00:00
|
|
|
/* archive current level, including all client edicts.
|
2010-11-25 16:36:27 +00:00
|
|
|
when the level is reloaded, they will be shells awaiting
|
|
|
|
a connecting client */
|
|
|
|
SV_WriteLevelFile();
|
|
|
|
|
|
|
|
/* save server state */
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_WriteServerFile(false);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
|
|
|
/* copy it off */
|
2012-07-21 08:06:07 +00:00
|
|
|
SV_CopySaveGame("current", dir);
|
2010-11-25 16:36:27 +00:00
|
|
|
|
2012-07-21 08:06:07 +00:00
|
|
|
Com_Printf("Done.\n");
|
2010-11-25 16:36:27 +00:00
|
|
|
}
|
2012-07-21 08:06:07 +00:00
|
|
|
|