Annotation of quake2/game/g_save.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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