Annotation of quake2/ctf/g_save.c, revision 1.1.1.2

1.1.1.2 ! root        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: */
1.1       root       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);
1.1.1.2 ! root      196:        filterban = gi.cvar ("filterban", "1", 0);
1.1       root      197: 
                    198:        g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE);
                    199: 
                    200:        run_pitch = gi.cvar ("run_pitch", "0.002", 0);
                    201:        run_roll = gi.cvar ("run_roll", "0.005", 0);
                    202:        bob_up  = gi.cvar ("bob_up", "0.005", 0);
                    203:        bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);
                    204:        bob_roll = gi.cvar ("bob_roll", "0.002", 0);
                    205: 
                    206:        // flood control
                    207:        flood_msgs = gi.cvar ("flood_msgs", "4", 0);
                    208:        flood_persecond = gi.cvar ("flood_persecond", "4", 0);
                    209:        flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0);
                    210: 
                    211:        // dm map list
                    212:        sv_maplist = gi.cvar ("sv_maplist", "", 0);
                    213: 
                    214:        // items
                    215:        InitItems ();
                    216: 
                    217:        Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
                    218: 
                    219:        Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
                    220: 
                    221:        // initialize all entities for this game
                    222:        game.maxentities = maxentities->value;
                    223:        g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
                    224:        globals.edicts = g_edicts;
                    225:        globals.max_edicts = game.maxentities;
                    226: 
                    227:        // initialize all clients for this game
                    228:        game.maxclients = maxclients->value;
                    229:        game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
                    230:        globals.num_edicts = game.maxclients+1;
                    231: 
                    232: //ZOID
                    233:        CTFInit();
                    234: //ZOID
                    235: }
                    236: 
                    237: //=========================================================
                    238: 
                    239: void WriteField1 (FILE *f, field_t *field, byte *base)
                    240: {
                    241:        void            *p;
                    242:        int                     len;
                    243:        int                     index;
                    244: 
                    245:        p = (void *)(base + field->ofs);
                    246:        switch (field->type)
                    247:        {
                    248:        case F_INT:
                    249:        case F_FLOAT:
                    250:        case F_ANGLEHACK:
                    251:        case F_VECTOR:
                    252:        case F_IGNORE:
                    253:                break;
                    254: 
                    255:        case F_LSTRING:
                    256:        case F_GSTRING:
                    257:                if ( *(char **)p )
                    258:                        len = strlen(*(char **)p) + 1;
                    259:                else
                    260:                        len = 0;
                    261:                *(int *)p = len;
                    262:                break;
                    263:        case F_EDICT:
                    264:                if ( *(edict_t **)p == NULL)
                    265:                        index = -1;
                    266:                else
                    267:                        index = *(edict_t **)p - g_edicts;
                    268:                *(int *)p = index;
                    269:                break;
                    270:        case F_CLIENT:
                    271:                if ( *(gclient_t **)p == NULL)
                    272:                        index = -1;
                    273:                else
                    274:                        index = *(gclient_t **)p - game.clients;
                    275:                *(int *)p = index;
                    276:                break;
                    277:        case F_ITEM:
                    278:                if ( *(edict_t **)p == NULL)
                    279:                        index = -1;
                    280:                else
                    281:                        index = *(gitem_t **)p - itemlist;
                    282:                *(int *)p = index;
                    283:                break;
                    284: 
                    285:        default:
                    286:                gi.error ("WriteEdict: unknown field type");
                    287:        }
                    288: }
                    289: 
                    290: void WriteField2 (FILE *f, field_t *field, byte *base)
                    291: {
                    292:        int                     len;
                    293:        void            *p;
                    294: 
                    295:        p = (void *)(base + field->ofs);
                    296:        switch (field->type)
                    297:        {
                    298:        case F_LSTRING:
                    299:        case F_GSTRING:
                    300:                if ( *(char **)p )
                    301:                {
                    302:                        len = strlen(*(char **)p) + 1;
                    303:                        fwrite (*(char **)p, len, 1, f);
                    304:                }
                    305:                break;
                    306:        }
                    307: }
                    308: 
                    309: void ReadField (FILE *f, field_t *field, byte *base)
                    310: {
                    311:        void            *p;
                    312:        int                     len;
                    313:        int                     index;
                    314: 
                    315:        p = (void *)(base + field->ofs);
                    316:        switch (field->type)
                    317:        {
                    318:        case F_INT:
                    319:        case F_FLOAT:
                    320:        case F_ANGLEHACK:
                    321:        case F_VECTOR:
                    322:        case F_IGNORE:
                    323:                break;
                    324: 
                    325:        case F_LSTRING:
                    326:                len = *(int *)p;
                    327:                if (!len)
                    328:                        *(char **)p = NULL;
                    329:                else
                    330:                {
                    331:                        *(char **)p = gi.TagMalloc (len, TAG_LEVEL);
                    332:                        fread (*(char **)p, len, 1, f);
                    333:                }
                    334:                break;
                    335:        case F_GSTRING:
                    336:                len = *(int *)p;
                    337:                if (!len)
                    338:                        *(char **)p = NULL;
                    339:                else
                    340:                {
                    341:                        *(char **)p = gi.TagMalloc (len, TAG_GAME);
                    342:                        fread (*(char **)p, len, 1, f);
                    343:                }
                    344:                break;
                    345:        case F_EDICT:
                    346:                index = *(int *)p;
                    347:                if ( index == -1 )
                    348:                        *(edict_t **)p = NULL;
                    349:                else
                    350:                        *(edict_t **)p = &g_edicts[index];
                    351:                break;
                    352:        case F_CLIENT:
                    353:                index = *(int *)p;
                    354:                if ( index == -1 )
                    355:                        *(gclient_t **)p = NULL;
                    356:                else
                    357:                        *(gclient_t **)p = &game.clients[index];
                    358:                break;
                    359:        case F_ITEM:
                    360:                index = *(int *)p;
                    361:                if ( index == -1 )
                    362:                        *(gitem_t **)p = NULL;
                    363:                else
                    364:                        *(gitem_t **)p = &itemlist[index];
                    365:                break;
                    366: 
                    367:        default:
                    368:                gi.error ("ReadEdict: unknown field type");
                    369:        }
                    370: }
                    371: 
                    372: //=========================================================
                    373: 
                    374: /*
                    375: ==============
                    376: WriteClient
                    377: 
                    378: All pointer variables (except function pointers) must be handled specially.
                    379: ==============
                    380: */
                    381: void WriteClient (FILE *f, gclient_t *client)
                    382: {
                    383:        field_t         *field;
                    384:        gclient_t       temp;
                    385:        
                    386:        // all of the ints, floats, and vectors stay as they are
                    387:        temp = *client;
                    388: 
                    389:        // change the pointers to lengths or indexes
                    390:        for (field=clientfields ; field->name ; field++)
                    391:        {
                    392:                WriteField1 (f, field, (byte *)&temp);
                    393:        }
                    394: 
                    395:        // write the block
                    396:        fwrite (&temp, sizeof(temp), 1, f);
                    397: 
                    398:        // now write any allocated data following the edict
                    399:        for (field=clientfields ; field->name ; field++)
                    400:        {
                    401:                WriteField2 (f, field, (byte *)client);
                    402:        }
                    403: }
                    404: 
                    405: /*
                    406: ==============
                    407: ReadClient
                    408: 
                    409: All pointer variables (except function pointers) must be handled specially.
                    410: ==============
                    411: */
                    412: void ReadClient (FILE *f, gclient_t *client)
                    413: {
                    414:        field_t         *field;
                    415: 
                    416:        fread (client, sizeof(*client), 1, f);
                    417: 
                    418:        for (field=clientfields ; field->name ; field++)
                    419:        {
                    420:                ReadField (f, field, (byte *)client);
                    421:        }
                    422: }
                    423: 
                    424: /*
                    425: ============
                    426: WriteGame
                    427: 
                    428: This will be called whenever the game goes to a new level,
                    429: and when the user explicitly saves the game.
                    430: 
                    431: Game information include cross level data, like multi level
                    432: triggers, help computer info, and all client states.
                    433: 
                    434: A single player death will automatically restore from the
                    435: last save position.
                    436: ============
                    437: */
                    438: void WriteGame (char *filename, qboolean autosave)
                    439: {
                    440:        FILE    *f;
                    441:        int             i;
                    442:        char    str[16];
                    443: 
                    444:        if (!autosave)
                    445:                SaveClientData ();
                    446: 
                    447:        f = fopen (filename, "wb");
                    448:        if (!f)
                    449:                gi.error ("Couldn't open %s", filename);
                    450: 
                    451:        memset (str, 0, sizeof(str));
                    452:        strcpy (str, __DATE__);
                    453:        fwrite (str, sizeof(str), 1, f);
                    454: 
                    455:        game.autosaved = autosave;
                    456:        fwrite (&game, sizeof(game), 1, f);
                    457:        game.autosaved = false;
                    458: 
                    459:        for (i=0 ; i<game.maxclients ; i++)
                    460:                WriteClient (f, &game.clients[i]);
                    461: 
                    462:        fclose (f);
                    463: }
                    464: 
                    465: void ReadGame (char *filename)
                    466: {
                    467:        FILE    *f;
                    468:        int             i;
                    469:        char    str[16];
                    470: 
                    471:        gi.FreeTags (TAG_GAME);
                    472: 
                    473:        f = fopen (filename, "rb");
                    474:        if (!f)
                    475:                gi.error ("Couldn't open %s", filename);
                    476: 
                    477:        fread (str, sizeof(str), 1, f);
                    478:        if (strcmp (str, __DATE__))
                    479:        {
                    480:                fclose (f);
                    481:                gi.error ("Savegame from an older version.\n");
                    482:        }
                    483: 
                    484:        g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
                    485:        globals.edicts = g_edicts;
                    486: 
                    487:        fread (&game, sizeof(game), 1, f);
                    488:        game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
                    489:        for (i=0 ; i<game.maxclients ; i++)
                    490:                ReadClient (f, &game.clients[i]);
                    491: 
                    492:        fclose (f);
                    493: }
                    494: 
                    495: //==========================================================
                    496: 
                    497: 
                    498: /*
                    499: ==============
                    500: WriteEdict
                    501: 
                    502: All pointer variables (except function pointers) must be handled specially.
                    503: ==============
                    504: */
                    505: void WriteEdict (FILE *f, edict_t *ent)
                    506: {
                    507:        field_t         *field;
                    508:        edict_t         temp;
                    509: 
                    510:        // all of the ints, floats, and vectors stay as they are
                    511:        temp = *ent;
                    512: 
                    513:        // change the pointers to lengths or indexes
                    514:        for (field=savefields ; field->name ; field++)
                    515:        {
                    516:                WriteField1 (f, field, (byte *)&temp);
                    517:        }
                    518: 
                    519:        // write the block
                    520:        fwrite (&temp, sizeof(temp), 1, f);
                    521: 
                    522:        // now write any allocated data following the edict
                    523:        for (field=savefields ; field->name ; field++)
                    524:        {
                    525:                WriteField2 (f, field, (byte *)ent);
                    526:        }
                    527: 
                    528: }
                    529: 
                    530: /*
                    531: ==============
                    532: WriteLevelLocals
                    533: 
                    534: All pointer variables (except function pointers) must be handled specially.
                    535: ==============
                    536: */
                    537: void WriteLevelLocals (FILE *f)
                    538: {
                    539:        field_t         *field;
                    540:        level_locals_t          temp;
                    541: 
                    542:        // all of the ints, floats, and vectors stay as they are
                    543:        temp = level;
                    544: 
                    545:        // change the pointers to lengths or indexes
                    546:        for (field=levelfields ; field->name ; field++)
                    547:        {
                    548:                WriteField1 (f, field, (byte *)&temp);
                    549:        }
                    550: 
                    551:        // write the block
                    552:        fwrite (&temp, sizeof(temp), 1, f);
                    553: 
                    554:        // now write any allocated data following the edict
                    555:        for (field=levelfields ; field->name ; field++)
                    556:        {
                    557:                WriteField2 (f, field, (byte *)&level);
                    558:        }
                    559: }
                    560: 
                    561: 
                    562: /*
                    563: ==============
                    564: ReadEdict
                    565: 
                    566: All pointer variables (except function pointers) must be handled specially.
                    567: ==============
                    568: */
                    569: void ReadEdict (FILE *f, edict_t *ent)
                    570: {
                    571:        field_t         *field;
                    572: 
                    573:        fread (ent, sizeof(*ent), 1, f);
                    574: 
                    575:        for (field=savefields ; field->name ; field++)
                    576:        {
                    577:                ReadField (f, field, (byte *)ent);
                    578:        }
                    579: }
                    580: 
                    581: /*
                    582: ==============
                    583: ReadLevelLocals
                    584: 
                    585: All pointer variables (except function pointers) must be handled specially.
                    586: ==============
                    587: */
                    588: void ReadLevelLocals (FILE *f)
                    589: {
                    590:        field_t         *field;
                    591: 
                    592:        fread (&level, sizeof(level), 1, f);
                    593: 
                    594:        for (field=levelfields ; field->name ; field++)
                    595:        {
                    596:                ReadField (f, field, (byte *)&level);
                    597:        }
                    598: }
                    599: 
                    600: /*
                    601: =================
                    602: WriteLevel
                    603: 
                    604: =================
                    605: */
                    606: void WriteLevel (char *filename)
                    607: {
                    608:        int             i;
                    609:        edict_t *ent;
                    610:        FILE    *f;
                    611:        void    *base;
                    612: 
                    613:        f = fopen (filename, "wb");
                    614:        if (!f)
                    615:                gi.error ("Couldn't open %s", filename);
                    616: 
                    617:        // write out edict size for checking
                    618:        i = sizeof(edict_t);
                    619:        fwrite (&i, sizeof(i), 1, f);
                    620: 
                    621:        // write out a function pointer for checking
                    622:        base = (void *)InitGame;
                    623:        fwrite (&base, sizeof(base), 1, f);
                    624: 
                    625:        // write out level_locals_t
                    626:        WriteLevelLocals (f);
                    627: 
                    628:        // write out all the entities
                    629:        for (i=0 ; i<globals.num_edicts ; i++)
                    630:        {
                    631:                ent = &g_edicts[i];
                    632:                if (!ent->inuse)
                    633:                        continue;
                    634:                fwrite (&i, sizeof(i), 1, f);
                    635:                WriteEdict (f, ent);
                    636:        }
                    637:        i = -1;
                    638:        fwrite (&i, sizeof(i), 1, f);
                    639: 
                    640:        fclose (f);
                    641: }
                    642: 
                    643: 
                    644: /*
                    645: =================
                    646: ReadLevel
                    647: 
                    648: SpawnEntities will allready have been called on the
                    649: level the same way it was when the level was saved.
                    650: 
                    651: That is necessary to get the baselines
                    652: set up identically.
                    653: 
                    654: The server will have cleared all of the world links before
                    655: calling ReadLevel.
                    656: 
                    657: No clients are connected yet.
                    658: =================
                    659: */
                    660: void ReadLevel (char *filename)
                    661: {
                    662:        int             entnum;
                    663:        FILE    *f;
                    664:        int             i;
                    665:        void    *base;
                    666:        edict_t *ent;
                    667: 
                    668:        f = fopen (filename, "rb");
                    669:        if (!f)
                    670:                gi.error ("Couldn't open %s", filename);
                    671: 
                    672:        // free any dynamic memory allocated by loading the level
                    673:        // base state
                    674:        gi.FreeTags (TAG_LEVEL);
                    675: 
                    676:        // wipe all the entities
                    677:        memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0]));
                    678:        globals.num_edicts = maxclients->value+1;
                    679: 
                    680:        // check edict size
                    681:        fread (&i, sizeof(i), 1, f);
                    682:        if (i != sizeof(edict_t))
                    683:        {
                    684:                fclose (f);
                    685:                gi.error ("ReadLevel: mismatched edict size");
                    686:        }
                    687: 
                    688:        // check function pointer base address
                    689:        fread (&base, sizeof(base), 1, f);
                    690:        if (base != (void *)InitGame)
                    691:        {
                    692:                fclose (f);
                    693:                gi.error ("ReadLevel: function pointers have moved");
                    694:        }
                    695: 
                    696:        // load the level locals
                    697:        ReadLevelLocals (f);
                    698: 
                    699:        // load all the entities
                    700:        while (1)
                    701:        {
                    702:                if (fread (&entnum, sizeof(entnum), 1, f) != 1)
                    703:                {
                    704:                        fclose (f);
                    705:                        gi.error ("ReadLevel: failed to read entnum");
                    706:                }
                    707:                if (entnum == -1)
                    708:                        break;
                    709:                if (entnum >= globals.num_edicts)
                    710:                        globals.num_edicts = entnum+1;
                    711: 
                    712:                ent = &g_edicts[entnum];
                    713:                ReadEdict (f, ent);
                    714: 
                    715:                // let the server rebuild world links for this ent
                    716:                memset (&ent->area, 0, sizeof(ent->area));
                    717:                gi.linkentity (ent);
                    718:        }
                    719: 
                    720:        fclose (f);
                    721: 
                    722:        // mark all clients as unconnected
                    723:        for (i=0 ; i<maxclients->value ; i++)
                    724:        {
                    725:                ent = &g_edicts[i+1];
                    726:                ent->client = game.clients + i;
                    727:                ent->client->pers.connected = false;
                    728:        }
                    729: 
                    730:        // do any load time things at this point
                    731:        for (i=0 ; i<globals.num_edicts ; i++)
                    732:        {
                    733:                ent = &g_edicts[i];
                    734: 
                    735:                if (!ent->inuse)
                    736:                        continue;
                    737: 
                    738:                // fire any cross-level triggers
                    739:                if (ent->classname)
                    740:                        if (strcmp(ent->classname, "target_crosslevel_target") == 0)
                    741:                                ent->nextthink = level.time + ent->delay;
                    742:        }
                    743: }
                    744: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.