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