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

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

unix.superglobalmegacorp.com

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