File: game\g_save.c

    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 */
  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 
  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 
  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         }
  319 }
  320 
  321 void ReadField (FILE *f, field_t *field, byte *base)
  322 {
  323         void            *p;
  324         int                     len;
  325         int                     index;
  326 
  327         if (field->flags & FFL_SPAWNTEMP)
  328                 return;
  329 
  330         p = (void *)(base + field->ofs);
  331         switch (field->type)
  332         {
  333         case F_INT:
  334         case F_FLOAT:
  335         case F_ANGLEHACK:
  336         case F_VECTOR:
  337         case F_IGNORE:
  338                 break;
  339 
  340         case F_LSTRING:
  341                 len = *(int *)p;
  342                 if (!len)
  343                         *(char **)p = NULL;
  344                 else
  345                 {
  346                         *(char **)p = gi.TagMalloc (len, TAG_LEVEL);
  347                         fread (*(char **)p, len, 1, f);
  348                 }
  349                 break;
  350         case F_EDICT:
  351                 index = *(int *)p;
  352                 if ( index == -1 )
  353                         *(edict_t **)p = NULL;
  354                 else
  355                         *(edict_t **)p = &g_edicts[index];
  356                 break;
  357         case F_CLIENT:
  358                 index = *(int *)p;
  359                 if ( index == -1 )
  360                         *(gclient_t **)p = NULL;
  361                 else
  362                         *(gclient_t **)p = &game.clients[index];
  363                 break;
  364         case F_ITEM:
  365                 index = *(int *)p;
  366                 if ( index == -1 )
  367                         *(gitem_t **)p = NULL;
  368                 else
  369                         *(gitem_t **)p = &itemlist[index];
  370                 break;
  371 
  372         //relative to code segment
  373         case F_FUNCTION:
  374                 index = *(int *)p;
  375                 if ( index == 0 )
  376                         *(byte **)p = NULL;
  377                 else
  378                         *(byte **)p = ((byte *)InitGame) + index;
  379                 break;
  380 
  381         //relative to data segment
  382         case F_MMOVE:
  383                 index = *(int *)p;
  384                 if (index == 0)
  385                         *(byte **)p = NULL;
  386                 else
  387                         *(byte **)p = (byte *)&mmove_reloc + index;
  388                 break;
  389 
  390         default:
  391                 gi.error ("ReadEdict: unknown field type");
  392         }
  393 }
  394 
  395 //=========================================================
  396 
  397 /*
  398 ==============
  399 WriteClient
  400 
  401 All pointer variables (except function pointers) must be handled specially.
  402 ==============
  403 */
  404 void WriteClient (FILE *f, gclient_t *client)
  405 {
  406         field_t         *field;
  407         gclient_t       temp;
  408         
  409         // all of the ints, floats, and vectors stay as they are
  410         temp = *client;
  411 
  412         // change the pointers to lengths or indexes
  413         for (field=clientfields ; field->name ; field++)
  414         {
  415                 WriteField1 (f, field, (byte *)&temp);
  416         }
  417 
  418         // write the block
  419         fwrite (&temp, sizeof(temp), 1, f);
  420 
  421         // now write any allocated data following the edict
  422         for (field=clientfields ; field->name ; field++)
  423         {
  424                 WriteField2 (f, field, (byte *)client);
  425         }
  426 }
  427 
  428 /*
  429 ==============
  430 ReadClient
  431 
  432 All pointer variables (except function pointers) must be handled specially.
  433 ==============
  434 */
  435 void ReadClient (FILE *f, gclient_t *client)
  436 {
  437         field_t         *field;
  438 
  439         fread (client, sizeof(*client), 1, f);
  440 
  441         for (field=clientfields ; field->name ; field++)
  442         {
  443                 ReadField (f, field, (byte *)client);
  444         }
  445 }
  446 
  447 /*
  448 ============
  449 WriteGame
  450 
  451 This will be called whenever the game goes to a new level,
  452 and when the user explicitly saves the game.
  453 
  454 Game information include cross level data, like multi level
  455 triggers, help computer info, and all client states.
  456 
  457 A single player death will automatically restore from the
  458 last save position.
  459 ============
  460 */
  461 void WriteGame (char *filename, qboolean autosave)
  462 {
  463         FILE    *f;
  464         int             i;
  465         char    str[16];
  466 
  467         if (!autosave)
  468                 SaveClientData ();
  469 
  470         f = fopen (filename, "wb");
  471         if (!f)
  472                 gi.error ("Couldn't open %s", filename);
  473 
  474         memset (str, 0, sizeof(str));
  475         strcpy (str, __DATE__);
  476         fwrite (str, sizeof(str), 1, f);
  477 
  478         game.autosaved = autosave;
  479         fwrite (&game, sizeof(game), 1, f);
  480         game.autosaved = false;
  481 
  482         for (i=0 ; i<game.maxclients ; i++)
  483                 WriteClient (f, &game.clients[i]);
  484 
  485         fclose (f);
  486 }
  487 
  488 void ReadGame (char *filename)
  489 {
  490         FILE    *f;
  491         int             i;
  492         char    str[16];
  493 
  494         gi.FreeTags (TAG_GAME);
  495 
  496         f = fopen (filename, "rb");
  497         if (!f)
  498                 gi.error ("Couldn't open %s", filename);
  499 
  500         fread (str, sizeof(str), 1, f);
  501         if (strcmp (str, __DATE__))
  502         {
  503                 fclose (f);
  504                 gi.error ("Savegame from an older version.\n");
  505         }
  506 
  507         g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
  508         globals.edicts = g_edicts;
  509 
  510         fread (&game, sizeof(game), 1, f);
  511         game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
  512         for (i=0 ; i<game.maxclients ; i++)
  513                 ReadClient (f, &game.clients[i]);
  514 
  515         fclose (f);
  516 }
  517 
  518 //==========================================================
  519 
  520 
  521 /*
  522 ==============
  523 WriteEdict
  524 
  525 All pointer variables (except function pointers) must be handled specially.
  526 ==============
  527 */
  528 void WriteEdict (FILE *f, edict_t *ent)
  529 {
  530         field_t         *field;
  531         edict_t         temp;
  532 
  533         // all of the ints, floats, and vectors stay as they are
  534         temp = *ent;
  535 
  536         // change the pointers to lengths or indexes
  537         for (field=fields ; field->name ; field++)
  538         {
  539                 WriteField1 (f, field, (byte *)&temp);
  540         }
  541 
  542         // write the block
  543         fwrite (&temp, sizeof(temp), 1, f);
  544 
  545         // now write any allocated data following the edict
  546         for (field=fields ; field->name ; field++)
  547         {
  548                 WriteField2 (f, field, (byte *)ent);
  549         }
  550 
  551 }
  552 
  553 /*
  554 ==============
  555 WriteLevelLocals
  556 
  557 All pointer variables (except function pointers) must be handled specially.
  558 ==============
  559 */
  560 void WriteLevelLocals (FILE *f)
  561 {
  562         field_t         *field;
  563         level_locals_t          temp;
  564 
  565         // all of the ints, floats, and vectors stay as they are
  566         temp = level;
  567 
  568         // change the pointers to lengths or indexes
  569         for (field=levelfields ; field->name ; field++)
  570         {
  571                 WriteField1 (f, field, (byte *)&temp);
  572         }
  573 
  574         // write the block
  575         fwrite (&temp, sizeof(temp), 1, f);
  576 
  577         // now write any allocated data following the edict
  578         for (field=levelfields ; field->name ; field++)
  579         {
  580                 WriteField2 (f, field, (byte *)&level);
  581         }
  582 }
  583 
  584 
  585 /*
  586 ==============
  587 ReadEdict
  588 
  589 All pointer variables (except function pointers) must be handled specially.
  590 ==============
  591 */
  592 void ReadEdict (FILE *f, edict_t *ent)
  593 {
  594         field_t         *field;
  595 
  596         fread (ent, sizeof(*ent), 1, f);
  597 
  598         for (field=fields ; field->name ; field++)
  599         {
  600                 ReadField (f, field, (byte *)ent);
  601         }
  602 }
  603 
  604 /*
  605 ==============
  606 ReadLevelLocals
  607 
  608 All pointer variables (except function pointers) must be handled specially.
  609 ==============
  610 */
  611 void ReadLevelLocals (FILE *f)
  612 {
  613         field_t         *field;
  614 
  615         fread (&level, sizeof(level), 1, f);
  616 
  617         for (field=levelfields ; field->name ; field++)
  618         {
  619                 ReadField (f, field, (byte *)&level);
  620         }
  621 }
  622 
  623 /*
  624 =================
  625 WriteLevel
  626 
  627 =================
  628 */
  629 void WriteLevel (char *filename)
  630 {
  631         int             i;
  632         edict_t *ent;
  633         FILE    *f;
  634         void    *base;
  635 
  636         f = fopen (filename, "wb");
  637         if (!f)
  638                 gi.error ("Couldn't open %s", filename);
  639 
  640         // write out edict size for checking
  641         i = sizeof(edict_t);
  642         fwrite (&i, sizeof(i), 1, f);
  643 
  644         // write out a function pointer for checking
  645         base = (void *)InitGame;
  646         fwrite (&base, sizeof(base), 1, f);
  647 
  648         // write out level_locals_t
  649         WriteLevelLocals (f);
  650 
  651         // write out all the entities
  652         for (i=0 ; i<globals.num_edicts ; i++)
  653         {
  654                 ent = &g_edicts[i];
  655                 if (!ent->inuse)
  656                         continue;
  657                 fwrite (&i, sizeof(i), 1, f);
  658                 WriteEdict (f, ent);
  659         }
  660         i = -1;
  661         fwrite (&i, sizeof(i), 1, f);
  662 
  663         fclose (f);
  664 }
  665 
  666 
  667 /*
  668 =================
  669 ReadLevel
  670 
  671 SpawnEntities will allready have been called on the
  672 level the same way it was when the level was saved.
  673 
  674 That is necessary to get the baselines
  675 set up identically.
  676 
  677 The server will have cleared all of the world links before
  678 calling ReadLevel.
  679 
  680 No clients are connected yet.
  681 =================
  682 */
  683 void ReadLevel (char *filename)
  684 {
  685         int             entnum;
  686         FILE    *f;
  687         int             i;
  688         void    *base;
  689         edict_t *ent;
  690 
  691         f = fopen (filename, "rb");
  692         if (!f)
  693                 gi.error ("Couldn't open %s", filename);
  694 
  695         // free any dynamic memory allocated by loading the level
  696         // base state
  697         gi.FreeTags (TAG_LEVEL);
  698 
  699         // wipe all the entities
  700         memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
  701         globals.num_edicts = maxclients->value+1;
  702 
  703         // check edict size
  704         fread (&i, sizeof(i), 1, f);
  705         if (i != sizeof(edict_t))
  706         {
  707                 fclose (f);
  708                 gi.error ("ReadLevel: mismatched edict size");
  709         }
  710 
  711         // check function pointer base address
  712         fread (&base, sizeof(base), 1, f);
  713 #ifdef _WIN32
  714         if (base != (void *)InitGame)
  715         {
  716                 fclose (f);
  717                 gi.error ("ReadLevel: function pointers have moved");
  718         }
719 #else 720 gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame));
721 #endif 722 723 // load the level locals 724 ReadLevelLocals (f); 725 726 // load all the entities 727 while (1) 728 { 729 if (fread (&entnum, sizeof(entnum), 1, f) != 1) 730 { 731 fclose (f); 732 gi.error ("ReadLevel: failed to read entnum"); 733 } 734 if (entnum == -1) 735 break; 736 if (entnum >= globals.num_edicts) 737 globals.num_edicts = entnum+1; 738 739 ent = &g_edicts[entnum]; 740 ReadEdict (f, ent); 741 742 // let the server rebuild world links for this ent 743 memset (&ent->area, 0, sizeof(ent->area)); 744 gi.linkentity (ent); 745 } 746 747 fclose (f); 748 749 // mark all clients as unconnected 750 for (i=0 ; i<maxclients->value ; i++) 751 { 752 ent = &g_edicts[i+1]; 753 ent->client = game.clients + i; 754 ent->client->pers.connected = false; 755 } 756 757 // do any load time things at this point 758 for (i=0 ; i<globals.num_edicts ; i++) 759 { 760 ent = &g_edicts[i]; 761 762 if (!ent->inuse) 763 continue; 764 765 // fire any cross-level triggers 766 if (ent->classname) 767 if (strcmp(ent->classname, "target_crosslevel_target") == 0) 768 ent->nextthink = level.time + ent->delay; 769 } 770 } 771