Annotation of quake2/client/cl_main.c, revision 1.1.1.1

1.1       root        1: // cl_main.c  -- client main loop
                      2: #include "client.h"
                      3: cvar_t *freelook;
                      4: 
                      5: cvar_t *adr0;
                      6: cvar_t *adr1;
                      7: cvar_t *adr2;
                      8: cvar_t *adr3;
                      9: cvar_t *adr4;
                     10: cvar_t *adr5;
                     11: cvar_t *adr6;
                     12: cvar_t *adr7;
                     13: cvar_t *adr8;
                     14: 
                     15: cvar_t *cl_stereo_separation;
                     16: cvar_t *cl_stereo;
                     17: cvar_t *rcon_client_password;
                     18: cvar_t *rcon_address;
                     19: 
                     20: cvar_t *cl_noskins;
                     21: cvar_t *cl_autoskins;
                     22: cvar_t *cl_footsteps;
                     23: cvar_t *cl_timeout;
                     24: cvar_t *cl_predict;
                     25: cvar_t *cl_minfps;
                     26: cvar_t *cl_maxfps;
                     27: cvar_t *cl_gun;
                     28: cvar_t *cl_add_particles;
                     29: cvar_t *cl_add_lights;
                     30: cvar_t *cl_add_entities;
                     31: cvar_t *cl_add_blend;
                     32: cvar_t *cl_shownet;
                     33: cvar_t *cl_showmiss;
                     34: cvar_t *cl_showclamp;
                     35: cvar_t *cl_paused;
                     36: cvar_t *cl_timedemo;
                     37: cvar_t *lookspring;
                     38: cvar_t *lookstrafe;
                     39: cvar_t *sensitivity;
                     40: cvar_t *m_pitch;
                     41: cvar_t *m_yaw;
                     42: cvar_t *m_forward;
                     43: cvar_t *m_side;
                     44: cvar_t *cl_lightlevel;
                     45: //
                     46: // userinfo
                     47: //
                     48: cvar_t *info_password;
                     49: cvar_t *name;
                     50: cvar_t *skin;
                     51: cvar_t *rate;
                     52: cvar_t *fov;
                     53: cvar_t *msg;
                     54: cvar_t *hand;
                     55: client_static_t        cls;
                     56: client_state_t cl;
                     57: centity_t              cl_entities[MAX_EDICTS];
                     58: 
                     59: entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
                     60: 
                     61: //======================================================================
                     62: 
                     63: 
                     64: /*
                     65: ====================
                     66: CL_WriteDemoMessage
                     67: 
                     68: Dumps the current net message, prefixed by the length
                     69: ====================
                     70: */
                     71: void CL_WriteDemoMessage (void)
                     72: {
                     73:        int             len, swlen;
                     74: 
                     75:        // the first eight bytes are just packet sequencing stuff
                     76:        len = net_message.cursize-8;
                     77:        swlen = LittleLong(len);
                     78:        fwrite (&swlen, 4, 1, cls.demofile);
                     79:        fwrite (net_message.data+8,     len, 1, cls.demofile);
                     80: }
                     81: 
                     82: 
                     83: /*
                     84: ====================
                     85: CL_Stop_f
                     86: 
                     87: stop recording a demo
                     88: ====================
                     89: */
                     90: void CL_Stop_f (void)
                     91: {
                     92:        int             len;
                     93: 
                     94:        if (!cls.demorecording)
                     95:        {
                     96:                Com_Printf ("Not recording a demo.\n");
                     97:                return;
                     98:        }
                     99: 
                    100: // finish up
                    101:        len = -1;
                    102:        fwrite (&len, 4, 1, cls.demofile);
                    103:        fclose (cls.demofile);
                    104:        cls.demofile = NULL;
                    105:        cls.demorecording = false;
                    106:        Com_Printf ("Stopped demo.\n");
                    107: }
                    108: 
                    109: /*
                    110: ====================
                    111: CL_Record_f
                    112: 
                    113: record <demoname>
                    114: 
                    115: Begins recording a demo from the current position
                    116: ====================
                    117: */
                    118: void CL_Record_f (void)
                    119: {
                    120:        char    name[MAX_OSPATH];
                    121:        char    buf_data[MAX_MSGLEN];
                    122:        sizebuf_t       buf;
                    123:        int             i;
                    124:        int             len;
                    125:        entity_state_t  *ent;
                    126:        entity_state_t  nullstate;
                    127: 
                    128:        if (Cmd_Argc() != 2)
                    129:        {
                    130:                Com_Printf ("record <demoname>\n");
                    131:                return;
                    132:        }
                    133: 
                    134:        if (cls.demorecording)
                    135:        {
                    136:                Com_Printf ("Already recording.\n");
                    137:                return;
                    138:        }
                    139: 
                    140:        if (cls.state != ca_active)
                    141:        {
                    142:                Com_Printf ("You must be in a level to record.\n");
                    143:                return;
                    144:        }
                    145: 
                    146:        //
                    147:        // open the demo file
                    148:        //
                    149:        Com_sprintf (name, sizeof(name), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv(1));
                    150: 
                    151:        Com_Printf ("recording to %s.\n", name);
                    152:        FS_CreatePath (name);
                    153:        cls.demofile = fopen (name, "wb");
                    154:        if (!cls.demofile)
                    155:        {
                    156:                Com_Printf ("ERROR: couldn't open.\n");
                    157:                return;
                    158:        }
                    159:        cls.demorecording = true;
                    160: 
                    161:        // don't start saving messages until a non-delta compressed message is received
                    162:        cls.demowaiting = true;
                    163: 
                    164:        //
                    165:        // write out messages to hold the startup information
                    166:        //
                    167:        SZ_Init (&buf, buf_data, sizeof(buf_data));
                    168: 
                    169:        // send the serverdata
                    170:        MSG_WriteByte (&buf, svc_serverdata);
                    171:        MSG_WriteLong (&buf, PROTOCOL_VERSION);
                    172:        MSG_WriteLong (&buf, 0x10000 + cl.servercount);
                    173:        MSG_WriteByte (&buf, 1);        // demos are always attract loops
                    174:        MSG_WriteString (&buf, cl.gamedir);
                    175:        MSG_WriteShort (&buf, cl.playernum);
                    176: 
                    177:        MSG_WriteString (&buf, cl.configstrings[CS_NAME]);
                    178: 
                    179:        // configstrings
                    180:        for (i=0 ; i<MAX_CONFIGSTRINGS ; i++)
                    181:        {
                    182:                if (cl.configstrings[i][0])
                    183:                {
                    184:                        if (buf.cursize + strlen (cl.configstrings[i]) + 32 > buf.maxsize)
                    185:                        {       // write it out
                    186:                                len = LittleLong (buf.cursize);
                    187:                                fwrite (&len, 4, 1, cls.demofile);
                    188:                                fwrite (buf.data, buf.cursize, 1, cls.demofile);
                    189:                                buf.cursize = 0;
                    190:                        }
                    191: 
                    192:                        MSG_WriteByte (&buf, svc_configstring);
                    193:                        MSG_WriteShort (&buf, i);
                    194:                        MSG_WriteString (&buf, cl.configstrings[i]);
                    195:                }
                    196: 
                    197:        }
                    198: 
                    199:        // baselines
                    200:        memset (&nullstate, 0, sizeof(nullstate));
                    201:        for (i=0; i<MAX_EDICTS ; i++)
                    202:        {
                    203:                ent = &cl_entities[i].baseline;
                    204:                if (!ent->modelindex)
                    205:                        continue;
                    206: 
                    207:                if (buf.cursize + 64 > buf.maxsize)
                    208:                {       // write it out
                    209:                        len = LittleLong (buf.cursize);
                    210:                        fwrite (&len, 4, 1, cls.demofile);
                    211:                        fwrite (buf.data, buf.cursize, 1, cls.demofile);
                    212:                        buf.cursize = 0;
                    213:                }
                    214: 
                    215:                MSG_WriteByte (&buf, svc_spawnbaseline);                
                    216:                MSG_WriteDeltaEntity (&nullstate, &cl_entities[i].baseline, &buf, true);
                    217:        }
                    218: 
                    219:        MSG_WriteByte (&buf, svc_stufftext);
                    220:        MSG_WriteString (&buf, "precache\n");
                    221: 
                    222:        // write it to the demo file
                    223: 
                    224:        len = LittleLong (buf.cursize);
                    225:        fwrite (&len, 4, 1, cls.demofile);
                    226:        fwrite (buf.data, buf.cursize, 1, cls.demofile);
                    227: 
                    228:        // the rest of the demo file will be individual frames
                    229: }
                    230: 
                    231: //======================================================================
                    232: /*
                    233: ===================
                    234: Cmd_ForwardToServer
                    235: adds the current command line as a clc_stringcmd to the client message.
                    236: things like godmode, noclip, etc, are commands directed to the server,
                    237: so when they are typed in at the console, they will need to be forwarded.
                    238: ===================
                    239: */
                    240: void Cmd_ForwardToServer (void)
                    241: {
                    242:        char    *cmd;
                    243: 
                    244:        cmd = Cmd_Argv(0);
                    245:        if (cls.state <= ca_connected || *cmd == '-' || *cmd == '+')
                    246:        {
                    247:                Com_Printf ("Unknown command \"%s\"\n", cmd);
                    248:                return;
                    249:        }
                    250: 
                    251:        MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
                    252:        SZ_Print (&cls.netchan.message, cmd);
                    253:        if (Cmd_Argc() > 1)
                    254:        {
                    255:                SZ_Print (&cls.netchan.message, " ");
                    256:                SZ_Print (&cls.netchan.message, Cmd_Args());
                    257:        }
                    258: }
                    259: void CL_Setenv_f( void )
                    260: {
                    261:        int argc = Cmd_Argc();
                    262:        if ( argc > 2 )
                    263:        {
                    264:                char buffer[1000];
                    265:                int i;
                    266:                strcpy( buffer, Cmd_Argv(1) );
                    267:                strcat( buffer, "=" );
                    268:                for ( i = 2; i < argc; i++ )
                    269:                {
                    270:                        strcat( buffer, Cmd_Argv( i ) );
                    271:                        strcat( buffer, " " );
                    272:                }
                    273:                putenv( buffer );
                    274:        }
                    275:        else if ( argc == 2 )
                    276:        {
                    277:                char *env = getenv( Cmd_Argv(1) );
                    278: 
                    279:                if ( env )
                    280:                {
                    281:                        Com_Printf( "%s=%s\n", Cmd_Argv(1), env );
                    282:                }
                    283:                else
                    284:                {
                    285:                        Com_Printf( "%s undefined\n", Cmd_Argv(1), env );
                    286:                }
                    287:        }
                    288: }
                    289: /*
                    290: ==================
                    291: CL_ForwardToServer_f
                    292: ==================
                    293: */
                    294: void CL_ForwardToServer_f (void)
                    295: {
                    296:        if (cls.state != ca_connected && cls.state != ca_active)
                    297:        {
                    298:                Com_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
                    299:                return;
                    300:        }
                    301:        
                    302:        // don't forward the first argument
                    303:        if (Cmd_Argc() > 1)
                    304:        {
                    305:                MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
                    306:                SZ_Print (&cls.netchan.message, Cmd_Args());
                    307:        }
                    308: }
                    309: /*
                    310: ==================
                    311: CL_Pause_f
                    312: ==================
                    313: */
                    314: void CL_Pause_f (void)
                    315: {
                    316:        // never pause in multiplayer
                    317:        if (Cvar_VariableValue ("maxclients") > 1 || !Com_ServerState ())
                    318:        {
                    319:                Cvar_SetValue ("paused", 0);
                    320:                return;
                    321:        }
                    322: 
                    323:        Cvar_SetValue ("paused", !cl_paused->value);
                    324: }
                    325: /*
                    326: ==================
                    327: CL_Quit_f
                    328: ==================
                    329: */
                    330: void CL_Quit_f (void)
                    331: {
                    332:        CL_Disconnect ();
                    333:        Com_Quit ();
                    334: }
                    335: /*
                    336: ================
                    337: CL_Drop
                    338: Called after an ERR_DROP was thrown
                    339: ================
                    340: */
                    341: void CL_Drop (void)
                    342: {
                    343:        if (cls.state == ca_uninitialized)
                    344:                return;
                    345:        if (cls.state == ca_disconnected)
                    346:                return;
                    347:        CL_Disconnect ();
                    348:        // drop loading plaque unless this is the initial game start
                    349:        if (cls.disable_servercount != -1)
                    350:                SCR_EndLoadingPlaque ();        // get rid of loading plaque
                    351: }
                    352: /*
                    353: =======================
                    354: CL_SendConnectPacket
                    355: 
                    356: We have gotten a challenge from the server, so try and
                    357: connect.
                    358: ======================
                    359: */
                    360: void CL_SendConnectPacket (void)
                    361: {
                    362:        netadr_t        adr;
                    363:        int             port;
                    364: 
                    365:        if (!NET_StringToAdr (cls.servername, &adr))
                    366:        {
                    367:                Com_Printf ("Bad server address\n");
                    368:                cls.connect_time = 0;
                    369:                return;
                    370:        }
                    371:        if (adr.port == 0)
                    372:                adr.port = BigShort (PORT_SERVER);
                    373: 
                    374:        port = Cvar_VariableValue ("qport");
                    375:        userinfo_modified = false;
                    376: 
                    377:        Netchan_OutOfBandPrint (NS_CLIENT, adr, "connect %i %i %i \"%s\"\n",
                    378:                PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo() );
                    379: }
                    380: 
                    381: /*
                    382: =================
                    383: CL_CheckForResend
                    384: Resend a connect message if the last one has timed out
                    385: =================
                    386: */
                    387: void CL_CheckForResend (void)
                    388: {
                    389:        netadr_t        adr;
                    390: 
                    391:        // if the local server is running and we aren't
                    392:        // then connect
                    393:        if (cls.state == ca_disconnected && Com_ServerState() )
                    394:        {
                    395:                cls.state = ca_connecting;
                    396:                strncpy (cls.servername, "localhost", sizeof(cls.servername)-1);
                    397:                // we don't need a challenge on the localhost
                    398:                CL_SendConnectPacket ();
                    399:                return;
                    400: //             cls.connect_time = -99999;      // CL_CheckForResend() will fire immediately
                    401:        }
                    402:        // resend if we haven't gotten a reply yet
                    403:        if (cls.state != ca_connecting)
                    404:                return;
                    405:        if (cls.realtime - cls.connect_time < 3000)
                    406:                return;
                    407: 
                    408:        if (!NET_StringToAdr (cls.servername, &adr))
                    409:        {
                    410:                Com_Printf ("Bad server address\n");
                    411:                cls.state = ca_disconnected;
                    412:                return;
                    413:        }
                    414:        if (adr.port == 0)
                    415:                adr.port = BigShort (PORT_SERVER);
                    416: 
                    417:        cls.connect_time = cls.realtime;        // for retransmit requests
                    418: 
                    419:        Com_Printf ("Connecting to %s...\n", cls.servername);
                    420: 
                    421:        Netchan_OutOfBandPrint (NS_CLIENT, adr, "getchallenge\n");
                    422: }
                    423: /*
                    424: ================
                    425: CL_Connect_f
                    426: ================
                    427: */
                    428: void CL_Connect_f (void)
                    429: {
                    430:        char    *server;
                    431:        if (Cmd_Argc() != 2)
                    432:        {
                    433:                Com_Printf ("usage: connect <server>\n");
                    434:                return; 
                    435:        }
                    436:        
                    437:        if (Com_ServerState ())
                    438:        {       // if running a local server, kill it and reissue
                    439:                SV_Shutdown (va("Server quit\n", msg), false);
                    440:        }
                    441:        else
                    442:        {
                    443:                CL_Disconnect ();
                    444:        }
                    445:        server = Cmd_Argv (1);
                    446:        NET_Config (true);              // allow remote
                    447:        CL_Disconnect ();
                    448:        cls.state = ca_connecting;
                    449:        strncpy (cls.servername, server, sizeof(cls.servername)-1);
                    450:        cls.connect_time = -99999;      // CL_CheckForResend() will fire immediately
                    451: }
                    452: /*
                    453: =====================
                    454: CL_Rcon_f
                    455:   Send the rest of the command line over as
                    456:   an unconnected command.
                    457: =====================
                    458: */
                    459: void CL_Rcon_f (void)
                    460: {
                    461:        char    message[1024];
                    462:        int             i;
                    463:        netadr_t        to;
                    464:        if (!rcon_client_password->string)
                    465:        {
                    466:                Com_Printf ("You must set 'rcon_password' before\n"
                    467:                                        "issuing an rcon command.\n");
                    468:                return;
                    469:        }
                    470:        message[0] = (char)255;
                    471:        message[1] = (char)255;
                    472:        message[2] = (char)255;
                    473:        message[3] = (char)255;
                    474:        message[4] = 0;
                    475: 
                    476:        NET_Config (true);              // allow remote
                    477:        strcat (message, "rcon ");
                    478:        strcat (message, rcon_client_password->string);
                    479:        strcat (message, " ");
                    480:        for (i=1 ; i<Cmd_Argc() ; i++)
                    481:        {
                    482:                strcat (message, Cmd_Argv(i));
                    483:                strcat (message, " ");
                    484:        }
                    485:        if (cls.state >= ca_connected)
                    486:                to = cls.netchan.remote_address;
                    487:        else
                    488:        {
                    489:                if (!strlen(rcon_address->string))
                    490:                {
                    491:                        Com_Printf ("You must either be connected,\n"
                    492:                                                "or set the 'rcon_address' cvar\n"
                    493:                                                "to issue rcon commands\n");
                    494:                        return;
                    495:                }
                    496:                NET_StringToAdr (rcon_address->string, &to);
                    497:                if (to.port == 0)
                    498:                        to.port = BigShort (PORT_SERVER);
                    499:        }
                    500:        
                    501:        NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to);
                    502: }
                    503: /*
                    504: =====================
                    505: CL_ClearState
                    506: =====================
                    507: */
                    508: void CL_ClearState (void)
                    509: {
                    510:        S_StopAllSounds ();
                    511:        CL_ClearEffects ();
                    512:        CL_ClearTEnts ();
                    513: // wipe the entire cl structure
                    514:        memset (&cl, 0, sizeof(cl));
                    515:        memset (&cl_entities, 0, sizeof(cl_entities));
                    516:        SZ_Clear (&cls.netchan.message);
                    517: }
                    518: /*
                    519: =====================
                    520: CL_Disconnect
                    521: Goes from a connected state to full screen console state
                    522: Sends a disconnect message to the server
                    523: This is also called on Com_Error, so it shouldn't cause any errors
                    524: =====================
                    525: */
                    526: void CL_Disconnect (void)
                    527: {
                    528:        byte    final[32];
                    529:        if (cls.state == ca_disconnected)
                    530:                return;
                    531:        if (cl_timedemo && cl_timedemo->value)
                    532:        {
                    533:                int     time;
                    534:                
                    535:                time = Sys_Milliseconds () - cl.timedemo_start;
                    536:                if (time > 0)
                    537:                        Com_Printf ("%i frames, %3.1f seconds: %3.1f fps\n", cl.timedemo_frames,
                    538:                        time/1000.0, cl.timedemo_frames*1000.0 / time);
                    539:        }
                    540:        VectorClear (cl.refdef.blend);
                    541:        re.CinematicSetPalette(NULL);
                    542: 
                    543:        M_ForceMenuOff ();
                    544:        cls.connect_time = 0;
                    545:        SCR_StopCinematic ();
                    546:        if (cls.demorecording)
                    547:                CL_Stop_f ();
                    548:        // send a disconnect message to the server
                    549:        final[0] = clc_stringcmd;
                    550:        strcpy ((char *)final+1, "disconnect");
                    551:        Netchan_Transmit (&cls.netchan, strlen(final), final);
                    552:        Netchan_Transmit (&cls.netchan, strlen(final), final);
                    553:        Netchan_Transmit (&cls.netchan, strlen(final), final);
                    554:        CL_ClearState ();
                    555:        cls.state = ca_disconnected;
                    556: }
                    557: void CL_Disconnect_f (void)
                    558: {
                    559:        Com_Error (ERR_DROP, "Disconnected from server");
                    560: }
                    561: /*
                    562: ====================
                    563: CL_Packet_f
                    564: packet <destination> <contents>
                    565: Contents allows \n escape character
                    566: ====================
                    567: */
                    568: void CL_Packet_f (void)
                    569: {
                    570:        char    send[2048];
                    571:        int             i, l;
                    572:        char    *in, *out;
                    573:        netadr_t        adr;
                    574:        if (Cmd_Argc() != 3)
                    575:        {
                    576:                Com_Printf ("packet <destination> <contents>\n");
                    577:                return;
                    578:        }
                    579:        NET_Config (true);              // allow remote
                    580:        if (!NET_StringToAdr (Cmd_Argv(1), &adr))
                    581:        {
                    582:                Com_Printf ("Bad address\n");
                    583:                return;
                    584:        }
                    585:        if (!adr.port)
                    586:                adr.port = BigShort (PORT_SERVER);
                    587:        in = Cmd_Argv(2);
                    588:        out = send+4;
                    589:        send[0] = send[1] = send[2] = send[3] = (char)0xff;
                    590:        l = strlen (in);
                    591:        for (i=0 ; i<l ; i++)
                    592:        {
                    593:                if (in[i] == '\\' && in[i+1] == 'n')
                    594:                {
                    595:                        *out++ = '\n';
                    596:                        i++;
                    597:                }
                    598:                else
                    599:                        *out++ = in[i];
                    600:        }
                    601:        *out = 0;
                    602:        NET_SendPacket (NS_CLIENT, out-send, send, adr);
                    603: }
                    604: /*
                    605: =================
                    606: CL_Changing_f
                    607: Just sent as a hint to the client that they should
                    608: drop to full console
                    609: =================
                    610: */
                    611: void CL_Changing_f (void)
                    612: {
                    613:        SCR_BeginLoadingPlaque ();
                    614:        cls.state = ca_connected;       // not active anymore, but not disconnected
                    615:        Com_Printf ("\nChanging map...\n");
                    616: }
                    617: /*
                    618: =================
                    619: CL_Reconnect_f
                    620: The server is changing levels
                    621: =================
                    622: */
                    623: void CL_Reconnect_f (void)
                    624: {
                    625:        S_StopAllSounds ();
                    626:        Com_Printf ("reconnecting...\n");
                    627:        cls.state = ca_connected;
                    628:        MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
                    629:        MSG_WriteString (&cls.netchan.message, "new");          
                    630: }
                    631: /*
                    632: =================
                    633: CL_ParseStatusMessage
                    634: Handle a reply from a ping
                    635: =================
                    636: */
                    637: void CL_ParseStatusMessage (void)
                    638: {
                    639:        char    *s;
                    640: 
                    641:        s = MSG_ReadString(&net_message);
                    642:        Com_Printf ("%s\n", s);
                    643:        M_AddToServerList (net_from, s);
                    644: }
                    645: /*
                    646: =================
                    647: CL_PingServers_f
                    648: =================
                    649: */
                    650: void CL_PingServers_f (void)
                    651: {
                    652:        int                     i;
                    653:        netadr_t        adr;
                    654:        char            name[32];
                    655:        char            *adrstring;
                    656:        cvar_t          *noudp;
                    657:        cvar_t          *noipx;
                    658:        NET_Config (true);              // allow remote
                    659:        // send a broadcast packet
                    660:        Com_Printf ("pinging broadcast...\n");
                    661: 
                    662:        noudp = Cvar_Get ("noudp", "0", CVAR_NOSET);
                    663:        if (!noudp->value)
                    664:        {
                    665:                adr.type = NA_BROADCAST;
                    666:                adr.port = BigShort(PORT_SERVER);
                    667:                Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
                    668:        }
                    669: 
                    670:        noipx = Cvar_Get ("noipx", "0", CVAR_NOSET);
                    671:        if (!noipx->value)
                    672:        {
                    673:                adr.type = NA_BROADCAST_IPX;
                    674:                adr.port = BigShort(PORT_SERVER);
                    675:                Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
                    676:        }
                    677:        // send a packet to each address book entry
                    678:        for (i=0 ; i<16 ; i++)
                    679:        {
                    680:                Com_sprintf (name, sizeof(name), "adr%i", i);
                    681:                adrstring = Cvar_VariableString (name);
                    682:                if (!adrstring || !adrstring[0])
                    683:                        continue;
                    684:                Com_Printf ("pinging %s...\n", adrstring);
                    685:                if (!NET_StringToAdr (adrstring, &adr))
                    686:                {
                    687:                        Com_Printf ("Bad address: %s\n", adrstring);
                    688:                        continue;
                    689:                }
                    690:                if (!adr.port)
                    691:                        adr.port = BigShort(PORT_SERVER);
                    692:                Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
                    693:        }
                    694: }
                    695: 
                    696: /*
                    697: =================
                    698: CL_Skins_f
                    699: 
                    700: Load or download any custom player skins and models
                    701: =================
                    702: */
                    703: void CL_Skins_f (void)
                    704: {
                    705:        int             i;
                    706: 
                    707:        for (i=0 ; i<MAX_CLIENTS ; i++)
                    708:        {
                    709:                if (!cl.configstrings[CS_PLAYERSKINS+i][0])
                    710:                        continue;
                    711:                Com_Printf ("client %i: %s\n", i, cl.configstrings[CS_PLAYERSKINS+i]); 
                    712:                SCR_UpdateScreen ();
                    713:                Sys_SendKeyEvents ();   // pump message loop
                    714:                CL_ParseClientinfo (i);
                    715:        }
                    716: }
                    717: 
                    718: /*
                    719: =================
                    720: CL_ConnectionlessPacket
                    721: Responses to broadcasts, etc
                    722: =================
                    723: */
                    724: void CL_ConnectionlessPacket (void)
                    725: {
                    726:        char    *s;
                    727:        char    *c;
                    728:        
                    729:        MSG_BeginReading (&net_message);
                    730:        MSG_ReadLong (&net_message);    // skip the -1
                    731:        s = MSG_ReadStringLine (&net_message);
                    732:        Cmd_TokenizeString (s, false);
                    733:        c = Cmd_Argv(0);
                    734:        Com_Printf ("%s: %s\n", NET_AdrToString (net_from), c);
                    735:        // server connection
                    736:        if (!strcmp(c, "client_connect"))
                    737:        {
                    738:                if (cls.state == ca_connected)
                    739:                {
                    740:                        Com_Printf ("Dup connect received.  Ignored.\n");
                    741:                        return;
                    742:                }
                    743:                Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.quakePort);
                    744:                MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
                    745:                MSG_WriteString (&cls.netchan.message, "new");  
                    746:                cls.state = ca_connected;
                    747:                return;
                    748:        }
                    749:        // server responding to a status broadcast
                    750:        if (!strcmp(c, "info"))
                    751:        {
                    752:                CL_ParseStatusMessage ();
                    753:                return;
                    754:        }
                    755:        // remote command from gui front end
                    756:        if (!strcmp(c, "cmd"))
                    757:        {
                    758:                if (!NET_IsLocalAddress(net_from))
                    759:                {
                    760:                        Com_Printf ("Command packet from remote host.  Ignored.\n");
                    761:                        return;
                    762:                }
                    763:                Sys_AppActivate ();
                    764:                s = MSG_ReadString (&net_message);
                    765:                Cbuf_AddText (s);
                    766:                Cbuf_AddText ("\n");
                    767:                return;
                    768:        }
                    769:        // print command from somewhere
                    770:        if (!strcmp(c, "print"))
                    771:        {
                    772:                s = MSG_ReadString (&net_message);
                    773:                Com_Printf (s);
                    774:                return;
                    775:        }
                    776:        // ping from somewhere
                    777:        if (!strcmp(c, "ping"))
                    778:        {
                    779:                Netchan_OutOfBandPrint (NS_CLIENT, net_from, "ack");
                    780:                return;
                    781:        }
                    782: 
                    783:        // challenge from the server we are connecting to
                    784:        if (!strcmp(c, "challenge"))
                    785:        {
                    786:                cls.challenge = atoi(Cmd_Argv(1));
                    787:                CL_SendConnectPacket ();
                    788:                return;
                    789:        }
                    790: 
                    791:        // echo request from server
                    792:        if (!strcmp(c, "echo"))
                    793:        {
                    794:                Netchan_OutOfBandPrint (NS_CLIENT, net_from, "%s", Cmd_Argv(1) );
                    795:                return;
                    796:        }
                    797: 
                    798:        Com_Printf ("Unknown command.\n");
                    799: }
                    800: /*
                    801: =================
                    802: CL_DumpPackets
                    803: 
                    804: A vain attempt to help bad TCP stacks that cause problems
                    805: when they overflow
                    806: =================
                    807: */
                    808: void CL_DumpPackets (void)
                    809: {
                    810:        while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
                    811:        {
                    812:                Com_Printf ("dumnping a packet\n");
                    813:        }
                    814: }
                    815: /*
                    816: =================
                    817: CL_ReadPackets
                    818: =================
                    819: */
                    820: void CL_ReadPackets (void)
                    821: {
                    822:        while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
                    823:        {
                    824: //     Com_Printf ("packet\n");
                    825:                //
                    826:                // remote command packet
                    827:                //
                    828:                if (*(int *)net_message.data == -1)
                    829:                {
                    830:                        CL_ConnectionlessPacket ();
                    831:                        continue;
                    832:                }
                    833:                if (cls.state == ca_disconnected || cls.state == ca_connecting)
                    834:                        continue;               // dump it if not connected
                    835:                if (net_message.cursize < 8)
                    836:                {
                    837:                        Com_Printf ("%s: Runt packet\n",NET_AdrToString(net_from));
                    838:                        continue;
                    839:                }
                    840:                //
                    841:                // packet from server
                    842:                //
                    843:                if (!NET_CompareAdr (net_from, cls.netchan.remote_address))
                    844:                {
                    845:                        Com_DPrintf ("%s:sequenced packet without connection\n"
                    846:                                ,NET_AdrToString(net_from));
                    847:                        continue;
                    848:                }
                    849:                if (!Netchan_Process(&cls.netchan, &net_message))
                    850:                        continue;               // wasn't accepted for some reason
                    851:                CL_ParseServerMessage ();
                    852:        }
                    853:        //
                    854:        // check timeout
                    855:        //
                    856:        if (cls.state >= ca_connected
                    857:         && cls.realtime - cls.netchan.last_received > cl_timeout->value*1000)
                    858:        {
                    859:                if (++cl.timeoutcount > 5)      // timeoutcount saves debugger
                    860:                {
                    861:                        Com_Printf ("\nServer connection timed out.\n");
                    862:                        CL_Disconnect ();
                    863:                        return;
                    864:                }
                    865:        }
                    866:        else
                    867:                cl.timeoutcount = 0;
                    868:        
                    869: }
                    870: //=============================================================================
                    871: /*
                    872: ==============
                    873: CL_Userinfo_f
                    874: ==============
                    875: */
                    876: void CL_Userinfo_f (void)
                    877: {
                    878:        Com_Printf ("User info settings:\n");
                    879:        Info_Print (Cvar_Userinfo());
                    880: }
                    881: /*
                    882: =================
                    883: CL_Snd_Restart_f
                    884: Restart the sound subsystem so it can pick up
                    885: new parameters and flush all sounds
                    886: =================
                    887: */
                    888: void CL_Snd_Restart_f (void)
                    889: {
                    890:        S_Shutdown ();
                    891:        S_Init ();
                    892:        CL_RegisterSounds ();
                    893: }
                    894: /*
                    895: =================
                    896: CL_Precache_f
                    897: The server will send this command right
                    898: before allowing the client into the server
                    899: =================
                    900: */
                    901: void CL_Precache_f (void)
                    902: {
                    903:        unsigned        map_checksum;           // for detecting cheater maps
                    904: 
                    905:        CM_LoadMap (cl.configstrings[CS_MODELS+1], true, &map_checksum);
                    906: 
                    907:        if (map_checksum != atoi(cl.configstrings[CS_MAPCHECKSUM]))
                    908:                Com_Error (ERR_DROP, "Local map version differs from server: %i != '%s'\n",
                    909:                map_checksum, cl.configstrings[CS_MAPCHECKSUM]);
                    910:        CL_RegisterSounds ();
                    911:        CL_PrepRefresh ();
                    912: }
                    913: /*
                    914: =================
                    915: CL_InitLocal
                    916: =================
                    917: */
                    918: void CL_InitLocal (void)
                    919: {
                    920:        cls.state = ca_disconnected;
                    921:        cls.realtime = Sys_Milliseconds ();
                    922:        CL_InitInput ();
                    923: 
                    924:        adr0 = Cvar_Get( "adr0", "", CVAR_ARCHIVE );
                    925:        adr1 = Cvar_Get( "adr1", "", CVAR_ARCHIVE );
                    926:        adr2 = Cvar_Get( "adr2", "", CVAR_ARCHIVE );
                    927:        adr3 = Cvar_Get( "adr3", "", CVAR_ARCHIVE );
                    928:        adr4 = Cvar_Get( "adr4", "", CVAR_ARCHIVE );
                    929:        adr5 = Cvar_Get( "adr5", "", CVAR_ARCHIVE );
                    930:        adr6 = Cvar_Get( "adr6", "", CVAR_ARCHIVE );
                    931:        adr7 = Cvar_Get( "adr7", "", CVAR_ARCHIVE );
                    932:        adr8 = Cvar_Get( "adr8", "", CVAR_ARCHIVE );
                    933: //
                    934: // register our variables
                    935: //
                    936:        cl_stereo_separation = Cvar_Get( "cl_stereo_separation", "0.4", CVAR_ARCHIVE );
                    937:        cl_stereo = Cvar_Get( "cl_stereo", "0", 0 );
                    938: 
                    939:        cl_add_blend = Cvar_Get ("cl_blend", "1", 0);
                    940:        cl_add_lights = Cvar_Get ("cl_lights", "1", 0);
                    941:        cl_add_particles = Cvar_Get ("cl_particles", "1", 0);
                    942:        cl_add_entities = Cvar_Get ("cl_entities", "1", 0);
                    943:        cl_gun = Cvar_Get ("cl_gun", "1", 0);
                    944:        cl_footsteps = Cvar_Get ("cl_footsteps", "1", 0);
                    945:        cl_noskins = Cvar_Get ("cl_noskins", "0", 0);
                    946:        cl_autoskins = Cvar_Get ("cl_autoskins", "0", 0);
                    947:        cl_predict = Cvar_Get ("cl_predict", "1", 0);
                    948:        cl_minfps = Cvar_Get ("cl_minfps", "5", 0);
                    949:        cl_maxfps = Cvar_Get ("cl_maxfps", "90", 0);
                    950:        cl_upspeed = Cvar_Get ("cl_upspeed", "200", 0);
                    951:        cl_forwardspeed = Cvar_Get ("cl_forwardspeed", "200", 0);
                    952:        cl_sidespeed = Cvar_Get ("cl_sidespeed", "200", 0);
                    953:        cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", 0);
                    954:        cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", 0);
                    955:        cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", 0);
                    956:        cl_run = Cvar_Get ("cl_run", "0", CVAR_ARCHIVE);
                    957:        freelook = Cvar_Get( "freelook", "0", CVAR_ARCHIVE );
                    958:        lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE);
                    959:        lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE);
                    960:        sensitivity = Cvar_Get ("sensitivity", "3", CVAR_ARCHIVE);
                    961: 
                    962:        m_pitch = Cvar_Get ("m_pitch", "0.022", CVAR_ARCHIVE);
                    963:        m_yaw = Cvar_Get ("m_yaw", "0.022", 0);
                    964:        m_forward = Cvar_Get ("m_forward", "1", 0);
                    965:        m_side = Cvar_Get ("m_side", "1", 0);
                    966: 
                    967:        cl_shownet = Cvar_Get ("cl_shownet", "0", 0);
                    968:        cl_showmiss = Cvar_Get ("cl_showmiss", "0", 0);
                    969:        cl_showclamp = Cvar_Get ("showclamp", "0", 0);
                    970:        cl_timeout = Cvar_Get ("cl_timeout", "120", 0);
                    971:        cl_paused = Cvar_Get ("paused", "0", 0);
                    972:        cl_timedemo = Cvar_Get ("timedemo", "0", 0);
                    973:        rcon_client_password = Cvar_Get ("rcon_password", "", 0);
                    974:        rcon_address = Cvar_Get ("rcon_address", "", 0);
                    975:        cl_lightlevel = Cvar_Get ("r_lightlevel", "0", 0);
                    976:        //
                    977:        // userinfo
                    978:        //
                    979:        info_password = Cvar_Get ("password", "", CVAR_USERINFO);
                    980:        name = Cvar_Get ("name", "unnamed", CVAR_USERINFO | CVAR_ARCHIVE);
                    981:        skin = Cvar_Get ("skin", "male/grunt", CVAR_USERINFO | CVAR_ARCHIVE);
                    982:        rate = Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE);        // FIXME
                    983:        msg = Cvar_Get ("msg", "1", CVAR_USERINFO | CVAR_ARCHIVE);
                    984:        hand = Cvar_Get ("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
                    985:        fov = Cvar_Get ("fov", "90", CVAR_USERINFO | CVAR_ARCHIVE);
                    986:        //
                    987:        // register our commands
                    988:        //
                    989:        Cmd_AddCommand ("cmd", CL_ForwardToServer_f);
                    990:        Cmd_AddCommand ("pause", CL_Pause_f);
                    991:        Cmd_AddCommand ("pingservers", CL_PingServers_f);
                    992:        Cmd_AddCommand ("skins", CL_Skins_f);
                    993:        Cmd_AddCommand ("userinfo", CL_Userinfo_f);
                    994:        Cmd_AddCommand ("snd_restart", CL_Snd_Restart_f);
                    995:        Cmd_AddCommand ("changing", CL_Changing_f);
                    996:        Cmd_AddCommand ("disconnect", CL_Disconnect_f);
                    997:        Cmd_AddCommand ("record", CL_Record_f);
                    998:        Cmd_AddCommand ("stop", CL_Stop_f);
                    999:        Cmd_AddCommand ("quit", CL_Quit_f);
                   1000:        Cmd_AddCommand ("connect", CL_Connect_f);
                   1001:        Cmd_AddCommand ("reconnect", CL_Reconnect_f);
                   1002:        Cmd_AddCommand ("rcon", CL_Rcon_f);
                   1003: 
                   1004: //     Cmd_AddCommand ("packet", CL_Packet_f); // this is dangerous to leave in
                   1005:        Cmd_AddCommand ("setenv", CL_Setenv_f );
                   1006:        Cmd_AddCommand ("precache", CL_Precache_f);
                   1007:        //
                   1008:        // forward to server commands
                   1009:        //
                   1010:        // the only thing this does is allow command completion
                   1011:        // to work -- all unknown commands are automatically
                   1012:        // forwarded to the server
                   1013:        Cmd_AddCommand ("wave", NULL);
                   1014:        Cmd_AddCommand ("inven", NULL);
                   1015:        Cmd_AddCommand ("kill", NULL);
                   1016:        Cmd_AddCommand ("use", NULL);
                   1017:        Cmd_AddCommand ("drop", NULL);
                   1018:        Cmd_AddCommand ("say", NULL);
                   1019:        Cmd_AddCommand ("say_team", NULL);
                   1020:        Cmd_AddCommand ("info", NULL);
                   1021:        Cmd_AddCommand ("prog", NULL);
                   1022:        Cmd_AddCommand ("give", NULL);
                   1023:        Cmd_AddCommand ("god", NULL);
                   1024:        Cmd_AddCommand ("notarget", NULL);
                   1025:        Cmd_AddCommand ("noclip", NULL);
                   1026:        Cmd_AddCommand ("invuse", NULL);
                   1027:        Cmd_AddCommand ("invprev", NULL);
                   1028:        Cmd_AddCommand ("invnext", NULL);
                   1029:        Cmd_AddCommand ("invdrop", NULL);
                   1030:        Cmd_AddCommand ("weapnext", NULL);
                   1031:        Cmd_AddCommand ("weapprev", NULL);
                   1032: }
                   1033: /*
                   1034: ===============
                   1035: CL_WriteConfiguration
                   1036: Writes key bindings and archived cvars to config.cfg
                   1037: ===============
                   1038: */
                   1039: void CL_WriteConfiguration (void)
                   1040: {
                   1041:        FILE    *f;
                   1042:        char    path[MAX_QPATH];
                   1043:        if (cls.state == ca_uninitialized)
                   1044:                return;
                   1045:        Com_sprintf (path, sizeof(path),"%s/config.cfg",FS_Gamedir());
                   1046:        f = fopen (path, "w");
                   1047:        if (!f)
                   1048:        {
                   1049:                Com_Printf ("Couldn't write config.cfg.\n");
                   1050:                return;
                   1051:        }
                   1052:        fprintf (f, "// generated by quake, do not modify\n");
                   1053:        Key_WriteBindings (f);
                   1054:        fclose (f);
                   1055:        Cvar_WriteVariables (path);
                   1056: }
                   1057: 
                   1058: /*
                   1059: ==================
                   1060: CL_FixCvarCheats
                   1061: 
                   1062: ==================
                   1063: */
                   1064: 
                   1065: typedef struct
                   1066: {
                   1067:        char    *name;
                   1068:        char    *value;
                   1069:        cvar_t  *var;
                   1070: } cheatvar_t;
                   1071: 
                   1072: cheatvar_t     cheatvars[] = {
                   1073:        {"timescale", "1"},
                   1074:        {"timedemo", "0"},
                   1075:        {"r_drawworld", "1"},
                   1076:        {"cl_testlights", "0"},
                   1077:        {"r_fullbright", "0"},
                   1078:        {"r_drawflat", "0"},
                   1079:        {"paused", "0"},
                   1080:        {"fixedtime", "0"},
                   1081:        {NULL, NULL}
                   1082: };
                   1083: 
                   1084: int            numcheatvars;
                   1085: 
                   1086: void CL_FixCvarCheats (void)
                   1087: {
                   1088:        int                     i;
                   1089:        cheatvar_t      *var;
                   1090: 
                   1091:        if ( !strcmp(cl.configstrings[CS_MAXCLIENTS], "1") 
                   1092:                || !cl.configstrings[CS_MAXCLIENTS][0] )
                   1093:                return;         // single player can cheat
                   1094: 
                   1095:        // find all the cvars if we haven't done it yet
                   1096:        if (!numcheatvars)
                   1097:        {
                   1098:                while (cheatvars[numcheatvars].name)
                   1099:                {
                   1100:                        cheatvars[numcheatvars].var = Cvar_Get (cheatvars[numcheatvars].name,
                   1101:                                        cheatvars[numcheatvars].value, 0);
                   1102:                        numcheatvars++;
                   1103:                }
                   1104:        }
                   1105: 
                   1106:        // make sure they are all set to the proper values
                   1107:        for (i=0, var = cheatvars ; i<numcheatvars ; i++, var++)
                   1108:        {
                   1109:                if ( strcmp (var->var->string, var->value) )
                   1110:                {
                   1111:                        Cvar_Set (var->name, var->value);
                   1112:                }
                   1113:        }
                   1114: }
                   1115: //============================================================================
                   1116: 
                   1117: /*
                   1118: ==================
                   1119: CL_SendCommand
                   1120: 
                   1121: ==================
                   1122: */
                   1123: void CL_SendCommand (void)
                   1124: {
                   1125:        // get new key events
                   1126:        Sys_SendKeyEvents ();
                   1127: 
                   1128:        // allow mice or other external controllers to add commands
                   1129:        IN_Commands ();
                   1130: 
                   1131:        // process console commands
                   1132:        Cbuf_Execute ();
                   1133: 
                   1134:        // fix any cheating cvars
                   1135:        CL_FixCvarCheats ();
                   1136: 
                   1137:        // send intentions now
                   1138:        CL_SendCmd ();
                   1139: 
                   1140:        // resend a connection request if necessary
                   1141:        CL_CheckForResend ();
                   1142: }
                   1143: /*
                   1144: ==================
                   1145: CL_Frame
                   1146: ==================
                   1147: */
                   1148: void CL_Frame (int msec)
                   1149: {
                   1150:        static int      extratime;
                   1151:        static int  lasttimecalled;
                   1152:        if (dedicated->value)
                   1153:                return;
                   1154:        extratime += msec;
                   1155: 
                   1156:        if (!cl_timedemo->value)
                   1157:        {
                   1158:                if (cls.state == ca_connected && extratime < 100)
                   1159:                        return;                 // don't flood packets out while connecting
                   1160:                if (extratime < 1000/cl_maxfps->value)
                   1161:                        return;                 // framerate is too high
                   1162:        }
                   1163: 
                   1164:        // let the mouse activate or deactivate
                   1165:        IN_Frame ();
                   1166:        // decide the simulation time
                   1167:        cls.frametime = extratime/1000.0;
                   1168:        cl.time += extratime;
                   1169:        cls.realtime = curtime;
                   1170:        extratime = 0;
                   1171:        if (cls.frametime > (1.0 / cl_minfps->value))
                   1172:                cls.frametime = (1.0 / cl_minfps->value);
                   1173:        // if in the debugger last frame, don't timeout
                   1174:        if (msec > 5000)
                   1175:                cls.netchan.last_received = Sys_Milliseconds ();
                   1176: 
                   1177:        // fetch results from server
                   1178:        CL_ReadPackets ();
                   1179: 
                   1180:        // send a new command message to the server
                   1181:        CL_SendCommand ();
                   1182: 
                   1183:        // predict all unacknowledged movements
                   1184:        CL_PredictMovement ();
                   1185:        // allow rendering DLL change
                   1186:        VID_CheckChanges ();
                   1187:        if (!cl.refresh_prepped && cls.state == ca_active)
                   1188:                CL_PrepRefresh ();
                   1189: 
                   1190:        // update the screen
                   1191:        if (host_speeds->value)
                   1192:                time_before_ref = Sys_Milliseconds ();
                   1193:        SCR_UpdateScreen ();
                   1194:        if (host_speeds->value)
                   1195:                time_after_ref = Sys_Milliseconds ();
                   1196:        // update audio
                   1197:        S_Update (cl.refdef.vieworg, cl.v_forward, cl.v_right, cl.v_up);
                   1198:        
                   1199:        CDAudio_Update();
                   1200: 
                   1201:        // advance local effects for next frame
                   1202:        CL_RunDLights ();
                   1203:        CL_RunLightStyles ();
                   1204:        SCR_RunCinematic ();
                   1205:        SCR_RunConsole ();
                   1206: 
                   1207:        cls.framecount++;
                   1208: 
                   1209:        if ( log_stats->value )
                   1210:        {
                   1211:                if ( cls.state == ca_active )
                   1212:                {
                   1213:                        if ( !lasttimecalled )
                   1214:                        {
                   1215:                                lasttimecalled = Sys_Milliseconds();
                   1216:                                if ( log_stats_file )
                   1217:                                        fprintf( log_stats_file, "0\n" );
                   1218:                        }
                   1219:                        else
                   1220:                        {
                   1221:                                int now = Sys_Milliseconds();
                   1222: 
                   1223:                                if ( log_stats_file )
                   1224:                                        fprintf( log_stats_file, "%d\n", now - lasttimecalled );
                   1225:                                lasttimecalled = now;
                   1226:                        }
                   1227:                }
                   1228:        }
                   1229: }
                   1230: //============================================================================
                   1231: /*
                   1232: ====================
                   1233: CL_Init
                   1234: ====================
                   1235: */
                   1236: void CL_Init (void)
                   1237: {
                   1238:        if (dedicated->value)
                   1239:                return;         // nothing running on the client
                   1240:        // all archived variables will now be loaded
                   1241:        Con_Init ();    
                   1242:        VID_Init ();
                   1243:        S_Init ();      // sound must be initialized after window is created
                   1244:        
                   1245:        V_Init ();
                   1246:        
                   1247:        net_message.data = net_message_buffer;
                   1248:        net_message.maxsize = sizeof(net_message_buffer);
                   1249:        M_Init ();      
                   1250:        
                   1251:        SCR_Init ();
                   1252:        cls.disable_screen = true;      // don't draw yet
                   1253:        CDAudio_Init ();
                   1254:        CL_InitLocal ();
                   1255:        IN_Init ();
                   1256: //     Cbuf_AddText ("exec autoexec.cfg\n");
                   1257:        FS_ExecAutoexec ();
                   1258:        Cbuf_Execute ();
                   1259: }
                   1260: /*
                   1261: ===============
                   1262: CL_Shutdown
                   1263: FIXME: this is a callback from Sys_Quit and Com_Error.  It would be better
                   1264: to run quit through here before the final handoff to the sys code.
                   1265: ===============
                   1266: */
                   1267: void CL_Shutdown(void)
                   1268: {
                   1269:        static qboolean isdown = false;
                   1270:        
                   1271:        if (isdown)
                   1272:        {
                   1273:                printf ("recursive shutdown\n");
                   1274:                return;
                   1275:        }
                   1276:        isdown = true;
                   1277:        CL_WriteConfiguration (); 
                   1278:        CDAudio_Shutdown ();
                   1279:        S_Shutdown();
                   1280:        IN_Shutdown ();
                   1281:        VID_Shutdown();
                   1282: }
                   1283: 
                   1284: 

unix.superglobalmegacorp.com

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