1 
2 #include "g_local.h"
3 
4 #define Function(f) {#f, f}
5 
6 mmove_t mmove_reloc;
7 
8 field_t fields[] = {
9 	{"classname", FOFS(classname), F_LSTRING},
10 	{"model", FOFS(model), F_LSTRING},
11 	{"spawnflags", FOFS(spawnflags), F_INT},
12 	{"speed", FOFS(speed), F_FLOAT},
13 	{"accel", FOFS(accel), F_FLOAT},
14 	{"decel", FOFS(decel), F_FLOAT},
15 	{"target", FOFS(target), F_LSTRING},
16 	{"targetname", FOFS(targetname), F_LSTRING},
17 	{"pathtarget", FOFS(pathtarget), F_LSTRING},
18 	{"deathtarget", FOFS(deathtarget), F_LSTRING},
19 	{"killtarget", FOFS(killtarget), F_LSTRING},
20 	{"combattarget", FOFS(combattarget), F_LSTRING},
21 	{"message", FOFS(message), F_LSTRING},
22 	{"team", FOFS(team), F_LSTRING},
23 	{"wait", FOFS(wait), F_FLOAT},
24 	{"delay", FOFS(delay), F_FLOAT},
25 	{"random", FOFS(random), F_FLOAT},
26 	{"move_origin", FOFS(move_origin), F_VECTOR},
27 	{"move_angles", FOFS(move_angles), F_VECTOR},
28 	{"style", FOFS(style), F_INT},
29 	{"count", FOFS(count), F_INT},
30 	{"health", FOFS(health), F_INT},
31 	{"sounds", FOFS(sounds), F_INT},
32 	{"light", 0, F_IGNORE},
33 	{"dmg", FOFS(dmg), F_INT},
34 	{"mass", FOFS(mass), F_INT},
35 	{"volume", FOFS(volume), F_FLOAT},
36 	{"attenuation", FOFS(attenuation), F_FLOAT},
37 	{"map", FOFS(map), F_LSTRING},
38 	{"origin", FOFS(s.origin), F_VECTOR},
39 	{"angles", FOFS(s.angles), F_VECTOR},
40 	{"angle", FOFS(s.angles), F_ANGLEHACK},
41 
42 	{"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN},
43 	{"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN},
44 	{"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN},
45 	{"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN},
46 	{"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN},
47 	{"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN},
48 	{"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN},
49 	{"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN},
50 	{"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN},
51 	{"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN},
52 	{"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN},
53 	{"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN},
54 	{"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN},
55 
56 	{"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN},
57 	{"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN},
58 	{"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN},
59 	{"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN},
60 	{"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN},
61 	{"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN},
62 	{"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN},
63 
64 	{"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN},
65 	{"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN},
66 	{"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN},
67 	{"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN},
68 	{"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN},
69 	{"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN},
70 	{"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN},
71 	{"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN},
72 	{"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN},
73 	{"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN},
74 	{"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN},
75 
76 	{"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN},
77 
78 	// temp spawn vars -- only valid when the spawn function is called
79 	{"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP},
80 	{"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP},
81 	{"height", STOFS(height), F_INT, FFL_SPAWNTEMP},
82 	{"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP},
83 	{"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP},
84 	{"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP},
85 
86 //need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves
87 	{"item", FOFS(item), F_ITEM},
88 
89 	{"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP},
90 	{"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP},
91 	{"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP},
92 	{"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP},
93 	{"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP},
94 	{"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},
95 	{"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},
96 	{"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},
97 	{"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP},
98 
99 	// ROGUE
100 	{"bad_area", FOFS(bad_area), F_EDICT},
101 	// while the hint_path stuff could be reassembled on the fly, no reason to be different
102 	{"hint_chain", FOFS(hint_chain), F_EDICT},
103 	{"monster_hint_chain", FOFS(monster_hint_chain), F_EDICT},
104 	{"target_hint_chain", FOFS(target_hint_chain), F_EDICT},
105 	//
106 	{"goal_hint", FOFS(monsterinfo.goal_hint), F_EDICT},
107 	{"badMedic1", FOFS(monsterinfo.badMedic1), F_EDICT},
108 	{"badMedic2", FOFS(monsterinfo.badMedic2), F_EDICT},
109 	{"last_player_enemy", FOFS(monsterinfo.last_player_enemy), F_EDICT},
110 	{"commander", FOFS(monsterinfo.commander), F_EDICT},
111 	{"blocked", FOFS(monsterinfo.blocked), F_MMOVE, FFL_NOSPAWN},
112 	{"duck", FOFS(monsterinfo.duck), F_MMOVE, FFL_NOSPAWN},
113 	{"unduck", FOFS(monsterinfo.unduck), F_MMOVE, FFL_NOSPAWN},
114 	{"sidestep", FOFS(monsterinfo.sidestep), F_MMOVE, FFL_NOSPAWN},
115 	// ROGUE
116 
117 	{0, 0, 0, 0}
118 
119 };
120 
121 field_t		levelfields[] =
122 {
123 	{"changemap", LLOFS(changemap), F_LSTRING},
124 
125 	{"sight_client", LLOFS(sight_client), F_EDICT},
126 	{"sight_entity", LLOFS(sight_entity), F_EDICT},
127 	{"sound_entity", LLOFS(sound_entity), F_EDICT},
128 	{"sound2_entity", LLOFS(sound2_entity), F_EDICT},
129 
130 	// ROGUE
131 	{"disguise_violator", LLOFS(disguise_violator), F_EDICT},
132 	// ROGUE
133 
134 	{NULL, 0, F_INT}
135 };
136 
137 field_t		clientfields[] =
138 {
139 	{"pers.weapon", CLOFS(pers.weapon), F_ITEM},
140 	{"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM},
141 	{"newweapon", CLOFS(newweapon), F_ITEM},
142 	// ROGUE
143 	{"owned_sphere", CLOFS(owned_sphere), F_EDICT},
144 	// ROGUE
145 
146 	{NULL, 0, F_INT}
147 };
148 
149 /*
150 ============
151 InitGame
152 
153 This will be called when the dll is first loaded, which
154 only happens when a new game is started or a save game
155 is loaded.
156 ============
157 */
InitGame(void)158 void InitGame (void)
159 {
160 	gi.dprintf ("==== InitGame ====\n");
161 
162 	gun_x = gi.cvar ("gun_x", "0", 0);
163 	gun_y = gi.cvar ("gun_y", "0", 0);
164 	gun_z = gi.cvar ("gun_z", "0", 0);
165 
166 	//FIXME: sv_ prefix is wrong for these
167 	sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0);
168 	sv_rollangle = gi.cvar ("sv_rollangle", "2", 0);
169 	sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0);
170 	sv_gravity = gi.cvar ("sv_gravity", "800", 0);
171 
172 	sv_stopspeed = gi.cvar ("sv_stopspeed", "100", 0);		// PGM - was #define in g_phys.c
173 
174 //ROGUE
175 	g_showlogic = gi.cvar ("g_showlogic", "0", 0);
176 	huntercam = gi.cvar ("huntercam", "1", CVAR_SERVERINFO|CVAR_LATCH);
177 	strong_mines = gi.cvar ("strong_mines", "0", 0);
178 	randomrespawn = gi.cvar ("randomrespawn", "0", 0);
179 //ROGUE
180 
181 	// noset vars
182 	dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET);
183 
184 	// latched vars
185 	sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH);
186 	gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH);
187 	gi.cvar ("gamedate", __DATE__ , CVAR_SERVERINFO | CVAR_LATCH);
188 
189 	maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
190 	maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO);
191 	deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);
192 	coop = gi.cvar ("coop", "0", CVAR_LATCH);
193 	skill = gi.cvar ("skill", "1", CVAR_LATCH);
194 	maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH);
195 	gamerules = gi.cvar ("gamerules", "0", CVAR_LATCH);			//PGM
196 
197 	// change anytime vars
198 	dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO);
199 	fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO);
200 	timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO);
201 	password = gi.cvar ("password", "", CVAR_USERINFO);
202 	spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO);
203 	filterban = gi.cvar ("filterban", "1", 0);
204 
205 	g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
206 
207 	run_pitch = gi.cvar ("run_pitch", "0.002", 0);
208 	run_roll = gi.cvar ("run_roll", "0.005", 0);
209 	bob_up  = gi.cvar ("bob_up", "0.005", 0);
210 	bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);
211 	bob_roll = gi.cvar ("bob_roll", "0.002", 0);
212 
213 	// flood control
214 	flood_msgs = gi.cvar ("flood_msgs", "4", 0);
215 	flood_persecond = gi.cvar ("flood_persecond", "4", 0);
216 	flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0);
217 
218 	// dm map list
219 	sv_maplist = gi.cvar ("sv_maplist", "", 0);
220 #ifdef WITH_ACEBOT
221 	//bots
222 	botchat = gi.cvar ("botchat", "1", CVAR_ARCHIVE); //<-------botchat
223 	botauto_respawn = gi.cvar ("botauto_respawn", "0", CVAR_ARCHIVE);
224 #endif
225 #ifdef GAME_MOD
226 	weap_shell = gi.cvar ("weap_shell", "1", CVAR_ARCHIVE);
227         alt_fire_blaster = gi.cvar ("alt_fire_blaster", "0", CVAR_ARCHIVE);
228 	eject_bullets = gi.cvar ("eject_bullets", "1", CVAR_ARCHIVE);
229 	eject_bullets_dm_coop = gi.cvar ("eject_bullets_dm_coop", "0", 0);
230 	opt_dm_scoreboard = gi.cvar ("opt_dm_scoreboard", "1", CVAR_ARCHIVE);
231 	help_min = gi.cvar ("help_min", "0", CVAR_ARCHIVE);
232 	camoffset = gi.cvar("camoffset", "10", CVAR_SERVERINFO);
233 #endif
234 
235 	InitItems ();
236 
237 	Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
238 
239 	Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
240 
241 	// initialize all entities for this game
242 	game.maxentities = maxentities->value;
243 	g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
244 	globals.edicts = g_edicts;
245 	globals.max_edicts = game.maxentities;
246 
247 	// initialize all clients for this game
248 	game.maxclients = maxclients->value;
249 	game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
250 	globals.num_edicts = game.maxclients+1;
251 
252 //======
253 //ROGUE
254 	if(gamerules)
255 	{
256 		InitGameRules();	// if there are game rules to set up, do so now.
257 	}
258 //ROGUE
259 //======
260 }
261 
262 //=========================================================
263 
WriteField1(FILE * f,field_t * field,byte * base)264 void WriteField1 (FILE *f, field_t *field, byte *base)
265 {
266 	void		*p;
267 	int			len;
268 	int			index;
269 
270 	if (field->flags & FFL_SPAWNTEMP)
271 		return;
272 
273 	p = (void *)(base + field->ofs);
274 	switch (field->type)
275 	{
276 	case F_INT:
277 	case F_FLOAT:
278 	case F_ANGLEHACK:
279 	case F_VECTOR:
280 	case F_IGNORE:
281 		break;
282 
283 	case F_LSTRING:
284 	case F_GSTRING:
285 		if ( *(char **)p )
286 			len = strlen(*(char **)p) + 1;
287 		else
288 			len = 0;
289 		*(int *)p = len;
290 		break;
291 	case F_EDICT:
292 		if ( *(edict_t **)p == NULL)
293 			index = -1;
294 		else
295 			index = *(edict_t **)p - g_edicts;
296 		*(int *)p = index;
297 		break;
298 	case F_CLIENT:
299 		if ( *(gclient_t **)p == NULL)
300 			index = -1;
301 		else
302 			index = *(gclient_t **)p - game.clients;
303 		*(int *)p = index;
304 		break;
305 	case F_ITEM:
306 		if ( *(edict_t **)p == NULL)
307 			index = -1;
308 		else
309 			index = *(gitem_t **)p - itemlist;
310 		*(int *)p = index;
311 		break;
312 
313 	//relative to code segment
314 	case F_FUNCTION:
315 		if (*(byte **)p == NULL)
316 			index = 0;
317 		else
318 			index = *(byte **)p - ((byte *)InitGame);
319 		*(int *)p = index;
320 		break;
321 
322 	//relative to data segment
323 	case F_MMOVE:
324 		if (*(byte **)p == NULL)
325 			index = 0;
326 		else
327 			index = *(byte **)p - (byte *)&mmove_reloc;
328 		*(int *)p = index;
329 		break;
330 
331 	default:
332 		gi.error ("WriteEdict: unknown field type");
333 	}
334 }
335 
336 
WriteField2(FILE * f,field_t * field,byte * base)337 void WriteField2 (FILE *f, field_t *field, byte *base)
338 {
339 	int			len;
340 	void		*p;
341 
342 	if (field->flags & FFL_SPAWNTEMP)
343 		return;
344 
345 	p = (void *)(base + field->ofs);
346 	switch (field->type)
347 	{
348 	case F_LSTRING:
349 		if ( *(char **)p )
350 		{
351 			len = strlen(*(char **)p) + 1;
352 			fwrite (*(char **)p, len, 1, f);
353 		}
354 		break;
355 	}
356 }
357 
ReadField(FILE * f,field_t * field,byte * base)358 void ReadField (FILE *f, field_t *field, byte *base)
359 {
360 	void		*p;
361 	int			len;
362 	int			index;
363 
364 	if (field->flags & FFL_SPAWNTEMP)
365 		return;
366 
367 	p = (void *)(base + field->ofs);
368 	switch (field->type)
369 	{
370 	case F_INT:
371 	case F_FLOAT:
372 	case F_ANGLEHACK:
373 	case F_VECTOR:
374 	case F_IGNORE:
375 		break;
376 
377 	case F_LSTRING:
378 		len = *(int *)p;
379 		if (!len)
380 			*(char **)p = NULL;
381 		else
382 		{
383 			*(char **)p = gi.TagMalloc (len, TAG_LEVEL);
384 			fread (*(char **)p, len, 1, f);
385 		}
386 		break;
387 	case F_EDICT:
388 		index = *(int *)p;
389 		if ( index == -1 )
390 			*(edict_t **)p = NULL;
391 		else
392 			*(edict_t **)p = &g_edicts[index];
393 		break;
394 	case F_CLIENT:
395 		index = *(int *)p;
396 		if ( index == -1 )
397 			*(gclient_t **)p = NULL;
398 		else
399 			*(gclient_t **)p = &game.clients[index];
400 		break;
401 	case F_ITEM:
402 		index = *(int *)p;
403 		if ( index == -1 )
404 			*(gitem_t **)p = NULL;
405 		else
406 			*(gitem_t **)p = &itemlist[index];
407 		break;
408 
409 	//relative to code segment
410 	case F_FUNCTION:
411 		index = *(int *)p;
412 		if ( index == 0 )
413 			*(byte **)p = NULL;
414 		else
415 			*(byte **)p = ((byte *)InitGame) + index;
416 		break;
417 
418 	//relative to data segment
419 	case F_MMOVE:
420 		index = *(int *)p;
421 		if (index == 0)
422 			*(byte **)p = NULL;
423 		else
424 			*(byte **)p = (byte *)&mmove_reloc + index;
425 		break;
426 
427 	default:
428 		gi.error ("ReadEdict: unknown field type");
429 	}
430 }
431 
432 //=========================================================
433 
434 /*
435 ==============
436 WriteClient
437 
438 All pointer variables (except function pointers) must be handled specially.
439 ==============
440 */
WriteClient(FILE * f,gclient_t * client)441 void WriteClient (FILE *f, gclient_t *client)
442 {
443 	field_t		*field;
444 	gclient_t	temp;
445 
446 	// all of the ints, floats, and vectors stay as they are
447 	temp = *client;
448 
449 	// change the pointers to lengths or indexes
450 	for (field=clientfields ; field->name ; field++)
451 	{
452 		WriteField1 (f, field, (byte *)&temp);
453 	}
454 
455 	// write the block
456 	fwrite (&temp, sizeof(temp), 1, f);
457 
458 	// now write any allocated data following the edict
459 	for (field=clientfields ; field->name ; field++)
460 	{
461 		WriteField2 (f, field, (byte *)client);
462 	}
463 }
464 
465 /*
466 ==============
467 ReadClient
468 
469 All pointer variables (except function pointers) must be handled specially.
470 ==============
471 */
ReadClient(FILE * f,gclient_t * client)472 void ReadClient (FILE *f, gclient_t *client)
473 {
474 	field_t		*field;
475 
476 	fread (client, sizeof(*client), 1, f);
477 
478 	for (field=clientfields ; field->name ; field++)
479 	{
480 		ReadField (f, field, (byte *)client);
481 	}
482 }
483 
484 /*
485 ============
486 WriteGame
487 
488 This will be called whenever the game goes to a new level,
489 and when the user explicitly saves the game.
490 
491 Game information include cross level data, like multi level
492 triggers, help computer info, and all client states.
493 
494 A single player death will automatically restore from the
495 last save position.
496 ============
497 */
WriteGame(char * filename,qboolean autosave)498 void WriteGame (char *filename, qboolean autosave)
499 {
500 	FILE	*f;
501 	int		i;
502 	char	str[16];
503 
504 	if (!autosave)
505 		SaveClientData ();
506 
507 	f = fopen (filename, "wb");
508 	if (!f)
509 		gi.error ("Couldn't open %s", filename);
510 
511 	memset (str, 0, sizeof(str));
512 	strcpy (str, __DATE__);
513 	fwrite (str, sizeof(str), 1, f);
514 
515 	game.autosaved = autosave;
516 	fwrite (&game, sizeof(game), 1, f);
517 	game.autosaved = false;
518 
519 	for (i=0 ; i<game.maxclients ; i++)
520 		WriteClient (f, &game.clients[i]);
521 
522 	fclose (f);
523 }
524 
ReadGame(char * filename)525 void ReadGame (char *filename)
526 {
527 	FILE	*f;
528 	int		i;
529 	char	str[16];
530 
531 	gi.FreeTags (TAG_GAME);
532 
533 	f = fopen (filename, "rb");
534 	if (!f)
535 		gi.error ("Couldn't open %s", filename);
536 
537 	fread (str, sizeof(str), 1, f);
538 	if (strcmp (str, __DATE__))
539 	{
540 		fclose (f);
541 		gi.error ("Savegame from an older version.\n");
542 	}
543 
544 	g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
545 	globals.edicts = g_edicts;
546 
547 	fread (&game, sizeof(game), 1, f);
548 	game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
549 	for (i=0 ; i<game.maxclients ; i++)
550 		ReadClient (f, &game.clients[i]);
551 
552 	fclose (f);
553 }
554 
555 //==========================================================
556 
557 
558 /*
559 ==============
560 WriteEdict
561 
562 All pointer variables (except function pointers) must be handled specially.
563 ==============
564 */
WriteEdict(FILE * f,edict_t * ent)565 void WriteEdict (FILE *f, edict_t *ent)
566 {
567 	field_t		*field;
568 	edict_t		temp;
569 
570 	// all of the ints, floats, and vectors stay as they are
571 	temp = *ent;
572 
573 	// change the pointers to lengths or indexes
574 	for (field=fields ; field->name ; field++)
575 	{
576 		WriteField1 (f, field, (byte *)&temp);
577 	}
578 
579 	// write the block
580 	fwrite (&temp, sizeof(temp), 1, f);
581 
582 	// now write any allocated data following the edict
583 	for (field=fields ; field->name ; field++)
584 	{
585 		WriteField2 (f, field, (byte *)ent);
586 	}
587 
588 }
589 
590 /*
591 ==============
592 WriteLevelLocals
593 
594 All pointer variables (except function pointers) must be handled specially.
595 ==============
596 */
WriteLevelLocals(FILE * f)597 void WriteLevelLocals (FILE *f)
598 {
599 	field_t		*field;
600 	level_locals_t		temp;
601 
602 	// all of the ints, floats, and vectors stay as they are
603 	temp = level;
604 
605 	// change the pointers to lengths or indexes
606 	for (field=levelfields ; field->name ; field++)
607 	{
608 		WriteField1 (f, field, (byte *)&temp);
609 	}
610 
611 	// write the block
612 	fwrite (&temp, sizeof(temp), 1, f);
613 
614 	// now write any allocated data following the edict
615 	for (field=levelfields ; field->name ; field++)
616 	{
617 		WriteField2 (f, field, (byte *)&level);
618 	}
619 }
620 
621 
622 /*
623 ==============
624 ReadEdict
625 
626 All pointer variables (except function pointers) must be handled specially.
627 ==============
628 */
ReadEdict(FILE * f,edict_t * ent)629 void ReadEdict (FILE *f, edict_t *ent)
630 {
631 	field_t		*field;
632 
633 	fread (ent, sizeof(*ent), 1, f);
634 
635 	for (field=fields ; field->name ; field++)
636 	{
637 		ReadField (f, field, (byte *)ent);
638 	}
639 }
640 
641 /*
642 ==============
643 ReadLevelLocals
644 
645 All pointer variables (except function pointers) must be handled specially.
646 ==============
647 */
ReadLevelLocals(FILE * f)648 void ReadLevelLocals (FILE *f)
649 {
650 	field_t		*field;
651 
652 	fread (&level, sizeof(level), 1, f);
653 
654 	for (field=levelfields ; field->name ; field++)
655 	{
656 		ReadField (f, field, (byte *)&level);
657 	}
658 }
659 
660 /*
661 =================
662 WriteLevel
663 
664 =================
665 */
WriteLevel(char * filename)666 void WriteLevel (char *filename)
667 {
668 	int		i;
669 	edict_t	*ent;
670 	FILE	*f;
671 	void	*base;
672 
673 	f = fopen (filename, "wb");
674 	if (!f)
675 		gi.error ("Couldn't open %s", filename);
676 
677 	// write out edict size for checking
678 	i = sizeof(edict_t);
679 	fwrite (&i, sizeof(i), 1, f);
680 
681 	// write out a function pointer for checking
682 	base = (void *)InitGame;
683 	fwrite (&base, sizeof(base), 1, f);
684 
685 	// write out level_locals_t
686 	WriteLevelLocals (f);
687 
688 	// write out all the entities
689 	for (i=0 ; i<globals.num_edicts ; i++)
690 	{
691 		ent = &g_edicts[i];
692 		if (!ent->inuse)
693 			continue;
694 		fwrite (&i, sizeof(i), 1, f);
695 		WriteEdict (f, ent);
696 	}
697 	i = -1;
698 	fwrite (&i, sizeof(i), 1, f);
699 
700 	fclose (f);
701 }
702 
703 
704 /*
705 =================
706 ReadLevel
707 
708 SpawnEntities will already have been called on the
709 level the same way it was when the level was saved.
710 
711 That is necessary to get the baselines
712 set up identically.
713 
714 The server will have cleared all of the world links before
715 calling ReadLevel.
716 
717 No clients are connected yet.
718 =================
719 */
ReadLevel(char * filename)720 void ReadLevel (char *filename)
721 {
722 	int		entnum;
723 	FILE	*f;
724 	int		i;
725 	void	*base;
726 	edict_t	*ent;
727 
728 	f = fopen (filename, "rb");
729 	if (!f)
730 		gi.error ("Couldn't open %s", filename);
731 
732 	// free any dynamic memory allocated by loading the level
733 	// base state
734 	gi.FreeTags (TAG_LEVEL);
735 
736 	// wipe all the entities
737 	memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
738 	globals.num_edicts = maxclients->value+1;
739 
740 	// check edict size
741 	fread (&i, sizeof(i), 1, f);
742 	if (i != sizeof(edict_t))
743 	{
744 		fclose (f);
745 		gi.error ("ReadLevel: mismatched edict size");
746 	}
747 
748 	// check function pointer base address
749 	fread (&base, sizeof(base), 1, f);
750 #ifdef _WIN32
751 	if (base != (void *)InitGame)
752 	{
753 		fclose (f);
754 		gi.error ("ReadLevel: function pointers have moved");
755 	}
756 #else
757 	gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
758 #endif
759 
760 	// load the level locals
761 	ReadLevelLocals (f);
762 
763 	// load all the entities
764 	while (1)
765 	{
766 		if (fread (&entnum, sizeof(entnum), 1, f) != 1)
767 		{
768 			fclose (f);
769 			gi.error ("ReadLevel: failed to read entnum");
770 		}
771 		if (entnum == -1)
772 			break;
773 		if (entnum >= globals.num_edicts)
774 			globals.num_edicts = entnum+1;
775 
776 		ent = &g_edicts[entnum];
777 		ReadEdict (f, ent);
778 
779 		// let the server rebuild world links for this ent
780 		memset (&ent->area, 0, sizeof(ent->area));
781 		gi.linkentity (ent);
782 	}
783 
784 	fclose (f);
785 
786 	// PMM - rebuild the hint path chains
787 //	InitHintPaths();
788 	// pmm
789 
790 	// mark all clients as unconnected
791 	for (i=0 ; i<maxclients->value ; i++)
792 	{
793 		ent = &g_edicts[i+1];
794 		ent->client = game.clients + i;
795 		ent->client->pers.connected = false;
796 	}
797 
798 	// do any load time things at this point
799 	for (i=0 ; i<globals.num_edicts ; i++)
800 	{
801 		ent = &g_edicts[i];
802 
803 		if (!ent->inuse)
804 			continue;
805 
806 		// fire any cross-level triggers
807 		if (ent->classname)
808 			if (strcmp(ent->classname, "target_crosslevel_target") == 0)
809 				ent->nextthink = level.time + ent->delay;
810 	}
811 }
812