DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
sv_save.c File Reference
#include "quakedef.h"
#include "prvm_cmds.h"
#include "sys.h"
+ Include dependency graph for sv_save.c:

Go to the source code of this file.

Macros

#define SAVEGAME_VERSION   5
 

Functions

void SV_Loadgame_f (cmd_state_t *cmd)
 
void SV_Savegame_f (cmd_state_t *cmd)
 
void SV_Savegame_to (prvm_prog_t *prog, const char *name)
 

Macro Definition Documentation

◆ SAVEGAME_VERSION

#define SAVEGAME_VERSION   5

Definition at line 33 of file sv_save.c.

Referenced by SV_Loadgame_f(), and SV_Savegame_to().

Function Documentation

◆ SV_Loadgame_f()

void SV_Loadgame_f ( cmd_state_t * cmd)

Definition at line 240 of file sv_save.c.

241{
242 prvm_prog_t *prog = SVVM_prog;
243 char filename[MAX_QPATH];
244 char mapname[MAX_QPATH];
245 float time;
246 const char *start;
247 const char *end;
248 const char *t;
249 char *text;
250 prvm_edict_t *ent;
251 int i, k, numbuffers;
252 int entnum;
253 int version;
254 float spawn_parms[NUM_SPAWN_PARMS];
255 prvm_stringbuffer_t *stringbuffer;
256
257 if (Cmd_Argc(cmd) != 2)
258 {
259 Con_Print("load <savename> : load a game\n");
260 return;
261 }
262
263 dp_strlcpy (filename, Cmd_Argv(cmd, 1), sizeof(filename));
264 FS_DefaultExtension (filename, ".sav", sizeof (filename));
265
266 Con_Printf("Loading game from %s...\n", filename);
267
269 host.hook.Disconnect(false, NULL);
270
273
274 cls.demonum = -1; // stop demo loop in case this fails
275
276 t = text = (char *)FS_LoadFile (filename, tempmempool, false, NULL);
277 if (!text)
278 {
279 Con_Print(CON_ERROR "ERROR: couldn't open.\n");
280 return;
281 }
282
284 Con_Printf("SV_Loadgame_f: loading version\n");
285
286 // version
287 COM_ParseToken_Simple(&t, false, false, true);
288 version = atoi(com_token);
290 {
291 Mem_Free(text);
292 Con_Printf(CON_ERROR "Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
293 return;
294 }
295
297 Con_Printf("SV_Loadgame_f: loading description\n");
298
299 // description
300 COM_ParseToken_Simple(&t, false, false, true);
301
302 for (i = 0;i < NUM_SPAWN_PARMS;i++)
303 {
304 COM_ParseToken_Simple(&t, false, false, true);
305 spawn_parms[i] = atof(com_token);
306 }
307 // skill
308 COM_ParseToken_Simple(&t, false, false, true);
309// this silliness is so we can load 1.06 save files, which have float skill values
310 current_skill = (int)(atof(com_token) + 0.5);
312
314 Con_Printf("SV_Loadgame_f: loading mapname\n");
315
316 // mapname
317 COM_ParseToken_Simple(&t, false, false, true);
319
321 Con_Printf("SV_Loadgame_f: loading time\n");
322
323 // time
324 COM_ParseToken_Simple(&t, false, false, true);
325 time = atof(com_token);
326
328 Con_Printf("SV_Loadgame_f: spawning server\n");
329
331 if (!sv.active)
332 {
333 Mem_Free(text);
334 Con_Printf(CON_ERROR "Couldn't load map \"%s\"\n", mapname);
335 return;
336 }
337 sv.paused = true; // pause until all clients connect
338 sv.loadgame = true;
339
341 Con_Printf("SV_Loadgame_f: loading light styles\n");
342
343// load the light styles
344
345 // -1 is the globals
346 entnum = -1;
347
348 for (i = 0;i < MAX_LIGHTSTYLES;i++)
349 {
350 // light style
351 start = t;
352 COM_ParseToken_Simple(&t, false, false, true);
353 // if this is a 64 lightstyle savegame produced by Quake, stop now
354 // we have to check this because darkplaces may save more than 64
355 if (com_token[0] == '{')
356 {
357 t = start;
358 break;
359 }
361 }
362
364 Con_Printf("SV_Loadgame_f: skipping until globals\n");
365
366 // now skip everything before the first opening brace
367 // (this is for forward compatibility, so that older versions (at
368 // least ones with this fix) can load savegames with extra data before the
369 // first brace, as might be produced by a later engine version)
370 for (;;)
371 {
372 start = t;
373 if (!COM_ParseToken_Simple(&t, false, false, true))
374 break;
375 if (com_token[0] == '{')
376 {
377 t = start;
378 break;
379 }
380 }
381
382 // unlink all entities
384
385// load the edicts out of the savegame file
386 end = t;
387 for (;;)
388 {
389 start = t;
390 while (COM_ParseToken_Simple(&t, false, false, true))
391 if (!strcmp(com_token, "}"))
392 break;
393 if (!COM_ParseToken_Simple(&start, false, false, true))
394 {
395 // end of file
396 break;
397 }
398 if (strcmp(com_token,"{"))
399 {
400 Mem_Free(text);
401 Host_Error ("%s: first token isn't a brace", __func__);
402 }
403
404 if (entnum == -1)
405 {
407 Con_Printf("SV_Loadgame_f: loading globals\n");
408
409 // parse the global vars
410 PRVM_ED_ParseGlobals (prog, start);
411
412 // restore the autocvar globals
414 }
415 else
416 {
417 // parse an edict
418 if (entnum >= MAX_EDICTS)
419 {
420 Mem_Free(text);
421 Host_Error("%s: too many edicts in save file (reached MAX_EDICTS %i)", __func__, MAX_EDICTS);
422 }
423 while (entnum >= prog->max_edicts)
425 ent = PRVM_EDICT_NUM(entnum);
426 memset(ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
427 ent->free = false;
428
430 Con_Printf("SV_Loadgame_f: loading edict %d\n", entnum);
431
432 PRVM_ED_ParseEdict (prog, start, ent, true);
433
434 // link it into the bsp tree
435 if (!ent->free)
436 SV_LinkEdict(ent);
437 }
438
439 end = t;
440 entnum++;
441 }
442
443 prog->num_edicts = entnum;
444 sv.time = time;
445
446 for (i = 0;i < NUM_SPAWN_PARMS;i++)
447 svs.clients[0].spawn_parms[i] = spawn_parms[i];
448
450 Con_Printf("SV_Loadgame_f: skipping until extended data\n");
451
452 // read extended data if present
453 // the extended data is stored inside a /* */ comment block, which the
454 // parser intentionally skips, so we have to check for it manually here
455 if(end)
456 {
457 while (*end == '\r' || *end == '\n')
458 end++;
459 if (end[0] == '/' && end[1] == '*' && (end[2] == '\r' || end[2] == '\n'))
460 {
462 Con_Printf("SV_Loadgame_f: loading extended data\n");
463
464 Con_Printf("Loading extended DarkPlaces savegame\n");
465 t = end + 2;
466 memset(sv.lightstyles[0], 0, sizeof(sv.lightstyles));
467 memset(sv.model_precache[0], 0, sizeof(sv.model_precache));
468 memset(sv.sound_precache[0], 0, sizeof(sv.sound_precache));
469 BufStr_Flush(prog);
470
471 while (COM_ParseToken_Simple(&t, false, false, true))
472 {
473 if (!strcmp(com_token, "sv.lightstyles"))
474 {
475 COM_ParseToken_Simple(&t, false, false, true);
476 i = atoi(com_token);
477 COM_ParseToken_Simple(&t, false, false, true);
478 if (i >= 0 && i < MAX_LIGHTSTYLES)
480 else
481 Con_Printf(CON_WARN "unsupported lightstyle %i \"%s\"\n", i, com_token);
482 }
483 else if (!strcmp(com_token, "sv.model_precache"))
484 {
485 COM_ParseToken_Simple(&t, false, false, true);
486 i = atoi(com_token);
487 COM_ParseToken_Simple(&t, false, false, true);
488 if (i >= 0 && i < MAX_MODELS)
489 {
491 sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, sv.model_precache[i][0] == '*' ? sv.worldname : NULL);
492 }
493 else
494 Con_Printf(CON_WARN "unsupported model %i \"%s\"\n", i, com_token);
495 }
496 else if (!strcmp(com_token, "sv.sound_precache"))
497 {
498 COM_ParseToken_Simple(&t, false, false, true);
499 i = atoi(com_token);
500 COM_ParseToken_Simple(&t, false, false, true);
501 if (i >= 0 && i < MAX_SOUNDS)
503 else
504 Con_Printf(CON_WARN "unsupported sound %i \"%s\"\n", i, com_token);
505 }
506 else if (!strcmp(com_token, "sv.buffer"))
507 {
508 if (COM_ParseToken_Simple(&t, false, false, true))
509 {
510 i = atoi(com_token);
511 if (i >= 0)
512 {
514 if (COM_ParseToken_Simple(&t, false, false, true))
515 k |= atoi(com_token);
516 if (!BufStr_FindCreateReplace(prog, i, k, "string"))
517 Con_Printf(CON_ERROR "failed to create stringbuffer %i\n", i);
518 }
519 else
520 Con_Printf(CON_WARN "unsupported stringbuffer index %i \"%s\"\n", i, com_token);
521 }
522 else
523 Con_Printf(CON_WARN "unexpected end of line when parsing sv.buffer (expected buffer index)\n");
524 }
525 else if (!strcmp(com_token, "sv.bufstr"))
526 {
527 if (!COM_ParseToken_Simple(&t, false, false, true))
528 Con_Printf(CON_WARN "unexpected end of line when parsing sv.bufstr\n");
529 else
530 {
531 i = atoi(com_token);
532 stringbuffer = BufStr_FindCreateReplace(prog, i, STRINGBUFFER_SAVED, "string");
533 if (stringbuffer)
534 {
535 if (COM_ParseToken_Simple(&t, false, false, true))
536 {
537 k = atoi(com_token);
538 if (COM_ParseToken_Simple(&t, false, false, true))
539 BufStr_Set(prog, stringbuffer, k, com_token);
540 else
541 Con_Printf(CON_WARN "unexpected end of line when parsing sv.bufstr (expected string)\n");
542 }
543 else
544 Con_Printf(CON_WARN "unexpected end of line when parsing sv.bufstr (expected strindex)\n");
545 }
546 else
547 Con_Printf(CON_ERROR "failed to create stringbuffer %i \"%s\"\n", i, com_token);
548 }
549 }
550 // skip any trailing text or unrecognized commands
551 while (COM_ParseToken_Simple(&t, true, false, true) && strcmp(com_token, "\n"))
552 ;
553 }
554 }
555 }
556 Mem_Free(text);
557
558 // remove all temporary flagged string buffers (ones created with BufStr_FindCreateReplace)
560 for (i = 0; i < numbuffers; i++)
561 {
563 if (stringbuffer->flags & STRINGBUFFER_TEMP)
564 BufStr_Del(prog, stringbuffer);
565 }
566
568 Con_Printf("SV_Loadgame_f: finished\n");
569
570 // make sure we're connected to loopback
573}
client_static_t cls
Definition cl_main.c:116
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
char com_token[MAX_INPUTLINE]
Definition common.c:39
qbool COM_ParseToken_Simple(const char **datapointer, qbool returnnewline, qbool parsebackslash, qbool parsecomments)
Definition common.c:463
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_WARN
Definition console.h:101
#define CON_ERROR
Definition console.h:102
string mapname
float time
float entnum
void Cvar_SetValueQuick(cvar_t *var, float value)
Definition cvar.c:473
void Cvar_UpdateAllAutoCvars(cvar_state_t *cvars)
called after loading a savegame
Definition cvar.c:365
void FS_DefaultExtension(char *path, const char *extension, size_t size_path)
Definition fs.c:3641
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
static int(ZEXPORT *qz_inflate)(z_stream *strm
static int const char * version
Definition fs.c:479
host_static_t host
Definition host.c:41
void Host_Error(const char *error,...)
Definition host.c:85
cvar_t developer_entityparsing
Definition host.c:53
void cmd(string command,...)
model_t * Mod_ForName(const char *name, qbool crash, qbool checkdisk, const char *parentname)
#define STRINGBUFFER_SAVED
Definition progsvm.h:496
#define STRINGBUFFER_TEMP
Definition progsvm.h:498
#define PRVM_EDICT_NUM(n)
Definition progsvm.h:867
const char * PRVM_ED_ParseEdict(prvm_prog_t *prog, const char *data, prvm_edict_t *ent, qbool saveload)
void PRVM_ED_ParseGlobals(prvm_prog_t *prog, const char *data)
Definition prvm_edict.c:940
void PRVM_MEM_IncreaseEdicts(prvm_prog_t *prog)
Definition prvm_edict.c:105
#define SVVM_prog
Definition progsvm.h:766
void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str)
Definition prvm_cmds.c:3902
void BufStr_Flush(prvm_prog_t *prog)
Definition prvm_cmds.c:3943
void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer)
Definition prvm_cmds.c:3926
prvm_stringbuffer_t * BufStr_FindCreateReplace(prvm_prog_t *prog, int bufindex, unsigned flags, const char *format)
Definition prvm_cmds.c:3867
int i
#define MAX_EDICTS
max number of objects in game world at once (32768 protocol limit)
Definition qdefs.h:105
#define MAX_LIGHTSTYLES
max flickering light styles in level (note: affects savegame format)
Definition qdefs.h:108
#define MAX_SOUNDS
max number of sounds loaded at once
Definition qdefs.h:107
#define MAX_QPATH
max length of a quake game pathname
Definition qdefs.h:169
#define MAX_MODELS
max number of models loaded at once (including during level transitions)
Definition qdefs.h:106
#define NULL
Definition qtypes.h:12
float prvm_vec_t
Definition qtypes.h:55
int current_skill
skill level for currently loaded level (in case the user changes the cvar while the level is running,...
Definition sv_ccmds.c:27
server_t sv
local server
Definition sv_main.c:223
#define NUM_SPAWN_PARMS
Definition server.h:180
void SV_SpawnServer(const char *map)
Definition sv_main.c:1811
void SV_LinkEdict(prvm_edict_t *ent)
Definition sv_phys.c:804
server_static_t svs
persistant server info
Definition sv_main.c:224
cvar_t skill
Definition sv_main.c:52
int integer
Definition cvar.h:73
void(* ConnectLocal)(void)
Definition host.h:55
void(* ToggleMenu)(void)
Definition host.h:57
struct host_static_t::@12 hook
void(* Disconnect)(qbool, const char *,...)
Definition host.h:56
prvm_vec_t * fp
Definition progsvm.h:102
union prvm_edict_t::@30 fields
qbool free
true if this edict is unused
Definition progsvm.h:93
int entityfields
number of vec_t fields in progs (some variables are 3)
Definition progsvm.h:548
int num_edicts
copies of some vars that were former read from sv
Definition progsvm.h:671
memexpandablearray_t stringbuffersarray
Definition progsvm.h:596
struct cmd_state_s * console_cmd
points to the relevant console command interpreter for this vm (cmd_local or &cmd_server),...
Definition progsvm.h:641
int max_edicts
number of edicts for which space has been (should be) allocated
Definition progsvm.h:673
unsigned char flags
Definition progsvm.h:505
struct client_s * clients
client slots
Definition server.h:30
double time
Definition server.h:76
char lightstyles[MAX_LIGHTSTYLES][64]
Definition server.h:122
qbool paused
Definition server.h:68
char sound_precache[MAX_SOUNDS][MAX_QPATH]
Definition server.h:121
world_t world
collision culling data
Definition server.h:106
qbool active
false if only a net client
Definition server.h:66
char model_precache[MAX_MODELS][MAX_QPATH]
Definition server.h:116
qbool loadgame
handle connections specially
Definition server.h:71
struct model_s * models[MAX_MODELS]
Definition server.h:117
char worldname[MAX_QPATH]
Definition server.h:110
#define SAVEGAME_VERSION
Definition sv_save.c:33
void World_UnlinkAll(world_t *world)
unlinks all entities (used before reallocation of edicts)
Definition world.c:159
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
Definition zone.c:763
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
Definition zone.c:780
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Free(mem)
Definition zone.h:96

References server_t::active, BufStr_Del(), BufStr_FindCreateReplace(), BufStr_Flush(), BufStr_Set(), server_static_t::clients, cls, cmd(), Cmd_Argc(), Cmd_Argv(), COM_ParseToken_Simple(), com_token, CON_ERROR, Con_Print(), Con_Printf(), CON_WARN, host_static_t::ConnectLocal, prvm_prog_t::console_cmd, current_skill, Cvar_SetValueQuick(), Cvar_UpdateAllAutoCvars(), client_static_t::demonum, developer_entityparsing, host_static_t::Disconnect, dp_strlcpy, prvm_prog_t::entityfields, entnum, prvm_edict_t::fields, prvm_stringbuffer_t::flags, prvm_edict_t::fp, prvm_edict_t::free, FS_DefaultExtension(), FS_LoadFile(), host_static_t::hook, host, Host_Error(), i, int(), cvar_t::integer, server_t::lightstyles, server_t::loadgame, mapname, MAX_EDICTS, prvm_prog_t::max_edicts, MAX_LIGHTSTYLES, MAX_MODELS, MAX_QPATH, MAX_SOUNDS, Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), Mem_Free, Mod_ForName(), server_t::model_precache, server_t::models, NULL, prvm_prog_t::num_edicts, NUM_SPAWN_PARMS, server_t::paused, PRVM_ED_ParseEdict(), PRVM_ED_ParseGlobals(), PRVM_EDICT_NUM, PRVM_MEM_IncreaseEdicts(), SAVEGAME_VERSION, skill, server_t::sound_precache, STRINGBUFFER_SAVED, STRINGBUFFER_TEMP, prvm_prog_t::stringbuffersarray, sv, SV_LinkEdict(), SV_SpawnServer(), svs, SVVM_prog, tempmempool, server_t::time, time, host_static_t::ToggleMenu, version, server_t::world, World_UnlinkAll(), and server_t::worldname.

Referenced by SV_InitOperatorCommands().

◆ SV_Savegame_f()

void SV_Savegame_f ( cmd_state_t * cmd)

Definition at line 188 of file sv_save.c.

189{
190 prvm_prog_t *prog = SVVM_prog;
191 char name[MAX_QPATH];
192
193 if (!sv.active)
194 {
195 Con_Print(CON_ERROR "Can't save - no server running.\n");
196 return;
197 }
198
199 if (Cmd_Argc(cmd) != 2)
200 {
201 Con_Print("save <savename> : save a game\n");
202 return;
203 }
204
205 if (strstr(Cmd_Argv(cmd, 1), ".."))
206 {
207 Con_Print(CON_ERROR "Relative pathnames are not allowed.\n");
208 return;
209 }
210
211 for (int i = 0; i < svs.maxclients; ++i)
212 if (svs.clients[i].active && PRVM_serveredictfloat(svs.clients[i].edict, deadflag))
213 {
214 Con_Print(CON_ERROR "Can't savegame with a dead player\n");
215 return;
216 }
217
218 // bones_was_here: intermission_running isn't declared in dpdefs, but it's used by
219 // id1 Quake, all Quake mods (afaict), Nexuiz and Xonotic.
220 if (PRVM_serverglobalfloat(intermission_running))
221 {
222 Con_Print(CON_ERROR "Can't save in intermission.\n");
223 return;
224 }
225
226 if (SV_IsLocalServer() != 1)
227 Con_Print(CON_WARN "Warning: saving a multiplayer game may have strange results when restored (to properly resume, all players must join in the same player slots and then the game can be reloaded).\n");
228
229 dp_strlcpy (name, Cmd_Argv(cmd, 1), sizeof (name));
230 FS_DefaultExtension (name, ".sav", sizeof (name));
231
232 SV_Savegame_to(prog, name);
233}
const GLchar * name
Definition glquake.h:601
float deadflag
Definition progsdefs.qc:149
#define PRVM_serverglobalfloat(fieldname)
Definition progsvm.h:177
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
int SV_IsLocalServer(void)
Definition sv_main.c:1783
int maxclients
number of svs.clients slots (updated by maxplayers command)
Definition server.h:28
void SV_Savegame_to(prvm_prog_t *prog, const char *name)
Definition sv_save.c:35

References server_t::active, server_static_t::clients, cmd(), Cmd_Argc(), Cmd_Argv(), CON_ERROR, Con_Print(), CON_WARN, deadflag, dp_strlcpy, FS_DefaultExtension(), i, MAX_QPATH, server_static_t::maxclients, name, PRVM_serveredictfloat, PRVM_serverglobalfloat, sv, SV_IsLocalServer(), SV_Savegame_to(), svs, and SVVM_prog.

Referenced by SV_InitOperatorCommands().

◆ SV_Savegame_to()

void SV_Savegame_to ( prvm_prog_t * prog,
const char * name )

Definition at line 35 of file sv_save.c.

36{
37 qfile_t *f;
38 int i, k, l, numbuffers, lightstyles = 64;
39 char comment[SAVEGAME_COMMENT_LENGTH+1];
40 char line[MAX_INPUTLINE];
42 char *s;
43
44 // first we have to figure out if this can be saved in 64 lightstyles
45 // (for Quake compatibility)
46 for (i=64 ; i<MAX_LIGHTSTYLES ; i++)
47 if (sv.lightstyles[i][0])
48 lightstyles = i+1;
49
50 isserver = prog == SVVM_prog;
51
52 Con_Printf("Saving game to %s...\n", name);
53 f = FS_OpenRealFile(name, "wb", false);
54 if (!f)
55 {
56 Con_Print(CON_ERROR "ERROR: couldn't open.\n");
57 return;
58 }
59
61
62 memset(comment, 0, sizeof(comment));
63 if(isserver)
64 dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)), (int)PRVM_serverglobalfloat(killed_monsters), (int)PRVM_serverglobalfloat(total_monsters));
65 else
66 dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", prog->name);
67 // convert space to _ to make stdio happy
68 // LadyHavoc: convert control characters to _ as well
69 for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
70 if (ISWHITESPACEORCONTROL(comment[i]))
71 comment[i] = '_';
72 comment[SAVEGAME_COMMENT_LENGTH] = '\0';
73
74 FS_Printf(f, "%s\n", comment);
75 if(isserver)
76 {
77 for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
78 FS_Printf(f, "%f\n", svs.clients[0].spawn_parms[i]);
79 FS_Printf(f, "%d\n", current_skill);
80 FS_Printf(f, "%s\n", sv.worldbasename);
81 FS_Printf(f, "%f\n",sv.time);
82 }
83 else
84 {
85 for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
86 FS_Printf(f, "(dummy)\n");
87 FS_Printf(f, "%d\n", 0);
88 FS_Printf(f, "%s\n", "(dummy)");
89 FS_Printf(f, "%f\n", host.realtime);
90 }
91
92 // write the light styles
93 for (i=0 ; i<lightstyles ; i++)
94 {
95 if (isserver && sv.lightstyles[i][0])
96 FS_Printf(f, "%s\n", sv.lightstyles[i]);
97 else
98 FS_Print(f,"m\n");
99 }
100
101 PRVM_ED_WriteGlobals (prog, f);
102 for (i=0 ; i<prog->num_edicts ; i++)
103 {
104 FS_Printf(f,"// edict %d\n", i);
105 //Con_Printf("edict %d...\n", i);
107 }
108
109#if 1
110 FS_Printf(f,"/*\n");
111 FS_Printf(f,"// DarkPlaces extended savegame\n");
112 // darkplaces extension - extra lightstyles, support for color lightstyles
113 for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
114 if (isserver && sv.lightstyles[i][0])
115 FS_Printf(f, "sv.lightstyles %i %s\n", i, sv.lightstyles[i]);
116
117 // darkplaces extension - model precaches
118 for (i=1 ; i<MAX_MODELS ; i++)
119 if (sv.model_precache[i][0])
120 FS_Printf(f,"sv.model_precache %i %s\n", i, sv.model_precache[i]);
121
122 // darkplaces extension - sound precaches
123 for (i=1 ; i<MAX_SOUNDS ; i++)
124 if (sv.sound_precache[i][0])
125 FS_Printf(f,"sv.sound_precache %i %s\n", i, sv.sound_precache[i]);
126
127 // darkplaces extension - save buffers
129 for (i = 0; i < numbuffers; i++)
130 {
132 if(stringbuffer && (stringbuffer->flags & STRINGBUFFER_SAVED))
133 {
134 FS_Printf(f,"sv.buffer %i %i \"string\"\n", i, stringbuffer->flags & STRINGBUFFER_QCFLAGS);
135 for(k = 0; k < stringbuffer->num_strings; k++)
136 {
137 if (!stringbuffer->strings[k])
138 continue;
139 // Parse the string a bit to turn special characters
140 // (like newline, specifically) into escape codes
141 s = stringbuffer->strings[k];
142 for (l = 0;l < (int)sizeof(line) - 2 && *s;)
143 {
144 if (*s == '\n')
145 {
146 line[l++] = '\\';
147 line[l++] = 'n';
148 }
149 else if (*s == '\r')
150 {
151 line[l++] = '\\';
152 line[l++] = 'r';
153 }
154 else if (*s == '\\')
155 {
156 line[l++] = '\\';
157 line[l++] = '\\';
158 }
159 else if (*s == '"')
160 {
161 line[l++] = '\\';
162 line[l++] = '"';
163 }
164 else
165 line[l++] = *s;
166 s++;
167 }
168 line[l] = '\0';
169 FS_Printf(f,"sv.bufstr %i %i \"%s\"\n", i, k, line);
170 }
171 }
172 }
173 FS_Printf(f,"*/\n");
174#endif
175
176 FS_Close (f);
177#ifdef __EMSCRIPTEN__
178 js_syncFS(false);
179#endif
180 Con_Print("done.\n");
181}
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
qfile_t * FS_OpenRealFile(const char *filepath, const char *mode, qbool quiet)
Definition fs.c:2901
int FS_Close(qfile_t *file)
Definition fs.c:2970
int FS_Printf(qfile_t *file, const char *format,...)
Definition fs.c:3273
int FS_Print(qfile_t *file, const char *msg)
Definition fs.c:3261
float isserver(void)
float killed_monsters
Definition progsdefs.qc:40
float total_monsters
Definition progsdefs.qc:37
string message
Definition progsdefs.qc:205
#define STRINGBUFFER_QCFLAGS
Definition progsvm.h:497
void PRVM_ED_Write(prvm_prog_t *prog, struct qfile_s *f, prvm_edict_t *ed)
const char * PRVM_GetString(prvm_prog_t *prog, int num)
void PRVM_ED_WriteGlobals(prvm_prog_t *prog, struct qfile_s *f)
#define PRVM_serveredictstring(ed, fieldname)
Definition progsvm.h:174
#define ISWHITESPACEORCONTROL(ch)
Definition qdefs.h:187
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define SAVEGAME_COMMENT_LENGTH
max comment length of savegame in menu
Definition qdefs.h:121
bool qbool
Definition qtypes.h:9
float f
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700
prvm_edict_t * edicts
Definition progsvm.h:680
char worldbasename[MAX_QPATH]
Definition server.h:109

References server_static_t::clients, CON_ERROR, Con_Print(), Con_Printf(), current_skill, dpsnprintf(), prvm_prog_t::edicts, f, prvm_stringbuffer_t::flags, FS_Close(), FS_OpenRealFile(), FS_Print(), FS_Printf(), host, i, int(), isserver(), ISWHITESPACEORCONTROL, killed_monsters, server_t::lightstyles, MAX_INPUTLINE, MAX_LIGHTSTYLES, MAX_MODELS, MAX_SOUNDS, Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), message, server_t::model_precache, name, prvm_prog_t::name, prvm_prog_t::num_edicts, NUM_SPAWN_PARMS, prvm_stringbuffer_t::num_strings, PRVM_ED_Write(), PRVM_ED_WriteGlobals(), PRVM_EDICT_NUM, PRVM_GetString(), PRVM_serveredictstring, PRVM_serverglobalfloat, host_static_t::realtime, SAVEGAME_COMMENT_LENGTH, SAVEGAME_VERSION, server_t::sound_precache, STRINGBUFFER_QCFLAGS, STRINGBUFFER_SAVED, prvm_prog_t::stringbuffersarray, prvm_stringbuffer_t::strings, sv, svs, SVVM_prog, server_t::time, total_monsters, and server_t::worldbasename.

Referenced by PRVM_Breakpoint(), PRVM_Crash(), and SV_Savegame_f().