Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

g_save.c (16949B)


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