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

1.1.1.4 ! root        1: /*
        !             2: Copyright (C) 1997-2001 Id Software, Inc.
        !             3: 
        !             4: This program is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU General Public License
        !             6: as published by the Free Software Foundation; either version 2
        !             7: of the License, or (at your option) any later version.
        !             8: 
        !             9: This program is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
        !            12: 
        !            13: See the GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with this program; if not, write to the Free Software
        !            17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            18: 
        !            19: */
1.1       root       20: // cl_main.c  -- client main loop
1.1.1.2   root       21: 
1.1       root       22: #include "client.h"
1.1.1.2   root       23: 
1.1       root       24: cvar_t *freelook;
                     25: 
                     26: cvar_t *adr0;
                     27: cvar_t *adr1;
                     28: cvar_t *adr2;
                     29: cvar_t *adr3;
                     30: cvar_t *adr4;
                     31: cvar_t *adr5;
                     32: cvar_t *adr6;
                     33: cvar_t *adr7;
                     34: cvar_t *adr8;
                     35: 
                     36: cvar_t *cl_stereo_separation;
                     37: cvar_t *cl_stereo;
1.1.1.2   root       38: 
1.1       root       39: cvar_t *rcon_client_password;
                     40: cvar_t *rcon_address;
                     41: 
                     42: cvar_t *cl_noskins;
                     43: cvar_t *cl_autoskins;
                     44: cvar_t *cl_footsteps;
                     45: cvar_t *cl_timeout;
                     46: cvar_t *cl_predict;
1.1.1.2   root       47: //cvar_t       *cl_minfps;
1.1       root       48: cvar_t *cl_maxfps;
                     49: cvar_t *cl_gun;
1.1.1.2   root       50: 
1.1       root       51: cvar_t *cl_add_particles;
                     52: cvar_t *cl_add_lights;
                     53: cvar_t *cl_add_entities;
                     54: cvar_t *cl_add_blend;
1.1.1.2   root       55: 
1.1       root       56: cvar_t *cl_shownet;
                     57: cvar_t *cl_showmiss;
                     58: cvar_t *cl_showclamp;
1.1.1.2   root       59: 
1.1       root       60: cvar_t *cl_paused;
                     61: cvar_t *cl_timedemo;
1.1.1.2   root       62: 
1.1       root       63: cvar_t *lookspring;
                     64: cvar_t *lookstrafe;
                     65: cvar_t *sensitivity;
1.1.1.2   root       66: 
1.1       root       67: cvar_t *m_pitch;
                     68: cvar_t *m_yaw;
                     69: cvar_t *m_forward;
                     70: cvar_t *m_side;
1.1.1.2   root       71: 
1.1       root       72: cvar_t *cl_lightlevel;
1.1.1.2   root       73: 
1.1       root       74: //
                     75: // userinfo
                     76: //
                     77: cvar_t *info_password;
1.1.1.3   root       78: cvar_t *info_spectator;
1.1       root       79: cvar_t *name;
                     80: cvar_t *skin;
                     81: cvar_t *rate;
                     82: cvar_t *fov;
                     83: cvar_t *msg;
                     84: cvar_t *hand;
1.1.1.2   root       85: cvar_t *gender;
                     86: cvar_t *gender_auto;
                     87: 
                     88: cvar_t *cl_vwep;
                     89: 
1.1       root       90: client_static_t        cls;
                     91: client_state_t cl;
1.1.1.2   root       92: 
1.1       root       93: centity_t              cl_entities[MAX_EDICTS];
                     94: 
                     95: entity_state_t cl_parse_entities[MAX_PARSE_ENTITIES];
                     96: 
1.1.1.2   root       97: extern cvar_t *allow_download;
                     98: extern cvar_t *allow_download_players;
                     99: extern cvar_t *allow_download_models;
                    100: extern cvar_t *allow_download_sounds;
                    101: extern cvar_t *allow_download_maps;
                    102: 
1.1       root      103: //======================================================================
                    104: 
                    105: 
                    106: /*
                    107: ====================
                    108: CL_WriteDemoMessage
                    109: 
                    110: Dumps the current net message, prefixed by the length
                    111: ====================
                    112: */
                    113: void CL_WriteDemoMessage (void)
                    114: {
                    115:        int             len, swlen;
                    116: 
                    117:        // the first eight bytes are just packet sequencing stuff
                    118:        len = net_message.cursize-8;
                    119:        swlen = LittleLong(len);
                    120:        fwrite (&swlen, 4, 1, cls.demofile);
                    121:        fwrite (net_message.data+8,     len, 1, cls.demofile);
                    122: }
                    123: 
                    124: 
                    125: /*
                    126: ====================
                    127: CL_Stop_f
                    128: 
                    129: stop recording a demo
                    130: ====================
                    131: */
                    132: void CL_Stop_f (void)
                    133: {
                    134:        int             len;
                    135: 
                    136:        if (!cls.demorecording)
                    137:        {
                    138:                Com_Printf ("Not recording a demo.\n");
                    139:                return;
                    140:        }
                    141: 
                    142: // finish up
                    143:        len = -1;
                    144:        fwrite (&len, 4, 1, cls.demofile);
                    145:        fclose (cls.demofile);
                    146:        cls.demofile = NULL;
                    147:        cls.demorecording = false;
                    148:        Com_Printf ("Stopped demo.\n");
                    149: }
                    150: 
                    151: /*
                    152: ====================
                    153: CL_Record_f
                    154: 
                    155: record <demoname>
                    156: 
                    157: Begins recording a demo from the current position
                    158: ====================
                    159: */
                    160: void CL_Record_f (void)
                    161: {
                    162:        char    name[MAX_OSPATH];
                    163:        char    buf_data[MAX_MSGLEN];
                    164:        sizebuf_t       buf;
                    165:        int             i;
                    166:        int             len;
                    167:        entity_state_t  *ent;
                    168:        entity_state_t  nullstate;
                    169: 
                    170:        if (Cmd_Argc() != 2)
                    171:        {
                    172:                Com_Printf ("record <demoname>\n");
                    173:                return;
                    174:        }
                    175: 
                    176:        if (cls.demorecording)
                    177:        {
                    178:                Com_Printf ("Already recording.\n");
                    179:                return;
                    180:        }
                    181: 
                    182:        if (cls.state != ca_active)
                    183:        {
                    184:                Com_Printf ("You must be in a level to record.\n");
                    185:                return;
                    186:        }
                    187: 
                    188:        //
                    189:        // open the demo file
                    190:        //
                    191:        Com_sprintf (name, sizeof(name), "%s/demos/%s.dm2", FS_Gamedir(), Cmd_Argv(1));
                    192: 
                    193:        Com_Printf ("recording to %s.\n", name);
                    194:        FS_CreatePath (name);
                    195:        cls.demofile = fopen (name, "wb");
                    196:        if (!cls.demofile)
                    197:        {
                    198:                Com_Printf ("ERROR: couldn't open.\n");
                    199:                return;
                    200:        }
                    201:        cls.demorecording = true;
                    202: 
                    203:        // don't start saving messages until a non-delta compressed message is received
                    204:        cls.demowaiting = true;
                    205: 
                    206:        //
                    207:        // write out messages to hold the startup information
                    208:        //
                    209:        SZ_Init (&buf, buf_data, sizeof(buf_data));
                    210: 
                    211:        // send the serverdata
                    212:        MSG_WriteByte (&buf, svc_serverdata);
                    213:        MSG_WriteLong (&buf, PROTOCOL_VERSION);
                    214:        MSG_WriteLong (&buf, 0x10000 + cl.servercount);
                    215:        MSG_WriteByte (&buf, 1);        // demos are always attract loops
                    216:        MSG_WriteString (&buf, cl.gamedir);
                    217:        MSG_WriteShort (&buf, cl.playernum);
                    218: 
                    219:        MSG_WriteString (&buf, cl.configstrings[CS_NAME]);
                    220: 
                    221:        // configstrings
                    222:        for (i=0 ; i<MAX_CONFIGSTRINGS ; i++)
                    223:        {
                    224:                if (cl.configstrings[i][0])
                    225:                {
                    226:                        if (buf.cursize + strlen (cl.configstrings[i]) + 32 > buf.maxsize)
                    227:                        {       // write it out
                    228:                                len = LittleLong (buf.cursize);
                    229:                                fwrite (&len, 4, 1, cls.demofile);
                    230:                                fwrite (buf.data, buf.cursize, 1, cls.demofile);
                    231:                                buf.cursize = 0;
                    232:                        }
                    233: 
                    234:                        MSG_WriteByte (&buf, svc_configstring);
                    235:                        MSG_WriteShort (&buf, i);
                    236:                        MSG_WriteString (&buf, cl.configstrings[i]);
                    237:                }
                    238: 
                    239:        }
                    240: 
                    241:        // baselines
                    242:        memset (&nullstate, 0, sizeof(nullstate));
                    243:        for (i=0; i<MAX_EDICTS ; i++)
                    244:        {
                    245:                ent = &cl_entities[i].baseline;
                    246:                if (!ent->modelindex)
                    247:                        continue;
                    248: 
                    249:                if (buf.cursize + 64 > buf.maxsize)
                    250:                {       // write it out
                    251:                        len = LittleLong (buf.cursize);
                    252:                        fwrite (&len, 4, 1, cls.demofile);
                    253:                        fwrite (buf.data, buf.cursize, 1, cls.demofile);
                    254:                        buf.cursize = 0;
                    255:                }
                    256: 
                    257:                MSG_WriteByte (&buf, svc_spawnbaseline);                
1.1.1.2   root      258:                MSG_WriteDeltaEntity (&nullstate, &cl_entities[i].baseline, &buf, true, true);
1.1       root      259:        }
                    260: 
                    261:        MSG_WriteByte (&buf, svc_stufftext);
                    262:        MSG_WriteString (&buf, "precache\n");
                    263: 
                    264:        // write it to the demo file
                    265: 
                    266:        len = LittleLong (buf.cursize);
                    267:        fwrite (&len, 4, 1, cls.demofile);
                    268:        fwrite (buf.data, buf.cursize, 1, cls.demofile);
                    269: 
                    270:        // the rest of the demo file will be individual frames
                    271: }
                    272: 
                    273: //======================================================================
1.1.1.2   root      274: 
1.1       root      275: /*
                    276: ===================
                    277: Cmd_ForwardToServer
1.1.1.2   root      278: 
1.1       root      279: adds the current command line as a clc_stringcmd to the client message.
                    280: things like godmode, noclip, etc, are commands directed to the server,
                    281: so when they are typed in at the console, they will need to be forwarded.
                    282: ===================
                    283: */
                    284: void Cmd_ForwardToServer (void)
                    285: {
                    286:        char    *cmd;
                    287: 
                    288:        cmd = Cmd_Argv(0);
                    289:        if (cls.state <= ca_connected || *cmd == '-' || *cmd == '+')
                    290:        {
                    291:                Com_Printf ("Unknown command \"%s\"\n", cmd);
                    292:                return;
                    293:        }
                    294: 
                    295:        MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
                    296:        SZ_Print (&cls.netchan.message, cmd);
                    297:        if (Cmd_Argc() > 1)
                    298:        {
                    299:                SZ_Print (&cls.netchan.message, " ");
                    300:                SZ_Print (&cls.netchan.message, Cmd_Args());
                    301:        }
                    302: }
1.1.1.2   root      303: 
1.1       root      304: void CL_Setenv_f( void )
                    305: {
                    306:        int argc = Cmd_Argc();
1.1.1.2   root      307: 
1.1       root      308:        if ( argc > 2 )
                    309:        {
                    310:                char buffer[1000];
                    311:                int i;
1.1.1.2   root      312: 
1.1       root      313:                strcpy( buffer, Cmd_Argv(1) );
                    314:                strcat( buffer, "=" );
1.1.1.2   root      315: 
1.1       root      316:                for ( i = 2; i < argc; i++ )
                    317:                {
                    318:                        strcat( buffer, Cmd_Argv( i ) );
                    319:                        strcat( buffer, " " );
                    320:                }
1.1.1.2   root      321: 
1.1       root      322:                putenv( buffer );
                    323:        }
                    324:        else if ( argc == 2 )
                    325:        {
                    326:                char *env = getenv( Cmd_Argv(1) );
                    327: 
                    328:                if ( env )
                    329:                {
                    330:                        Com_Printf( "%s=%s\n", Cmd_Argv(1), env );
                    331:                }
                    332:                else
                    333:                {
                    334:                        Com_Printf( "%s undefined\n", Cmd_Argv(1), env );
                    335:                }
                    336:        }
                    337: }
1.1.1.2   root      338: 
                    339: 
1.1       root      340: /*
                    341: ==================
                    342: CL_ForwardToServer_f
                    343: ==================
                    344: */
                    345: void CL_ForwardToServer_f (void)
                    346: {
                    347:        if (cls.state != ca_connected && cls.state != ca_active)
                    348:        {
                    349:                Com_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
                    350:                return;
                    351:        }
                    352:        
                    353:        // don't forward the first argument
                    354:        if (Cmd_Argc() > 1)
                    355:        {
                    356:                MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
                    357:                SZ_Print (&cls.netchan.message, Cmd_Args());
                    358:        }
                    359: }
1.1.1.2   root      360: 
                    361: 
1.1       root      362: /*
                    363: ==================
                    364: CL_Pause_f
                    365: ==================
                    366: */
                    367: void CL_Pause_f (void)
                    368: {
                    369:        // never pause in multiplayer
                    370:        if (Cvar_VariableValue ("maxclients") > 1 || !Com_ServerState ())
                    371:        {
                    372:                Cvar_SetValue ("paused", 0);
                    373:                return;
                    374:        }
                    375: 
                    376:        Cvar_SetValue ("paused", !cl_paused->value);
                    377: }
1.1.1.2   root      378: 
1.1       root      379: /*
                    380: ==================
                    381: CL_Quit_f
                    382: ==================
                    383: */
                    384: void CL_Quit_f (void)
                    385: {
                    386:        CL_Disconnect ();
                    387:        Com_Quit ();
                    388: }
1.1.1.2   root      389: 
1.1       root      390: /*
                    391: ================
                    392: CL_Drop
1.1.1.2   root      393: 
1.1       root      394: Called after an ERR_DROP was thrown
                    395: ================
                    396: */
                    397: void CL_Drop (void)
                    398: {
                    399:        if (cls.state == ca_uninitialized)
                    400:                return;
                    401:        if (cls.state == ca_disconnected)
                    402:                return;
1.1.1.2   root      403: 
1.1       root      404:        CL_Disconnect ();
1.1.1.2   root      405: 
1.1       root      406:        // drop loading plaque unless this is the initial game start
                    407:        if (cls.disable_servercount != -1)
                    408:                SCR_EndLoadingPlaque ();        // get rid of loading plaque
                    409: }
1.1.1.2   root      410: 
                    411: 
1.1       root      412: /*
                    413: =======================
                    414: CL_SendConnectPacket
                    415: 
                    416: We have gotten a challenge from the server, so try and
                    417: connect.
                    418: ======================
                    419: */
                    420: void CL_SendConnectPacket (void)
                    421: {
                    422:        netadr_t        adr;
                    423:        int             port;
                    424: 
                    425:        if (!NET_StringToAdr (cls.servername, &adr))
                    426:        {
                    427:                Com_Printf ("Bad server address\n");
                    428:                cls.connect_time = 0;
                    429:                return;
                    430:        }
                    431:        if (adr.port == 0)
                    432:                adr.port = BigShort (PORT_SERVER);
                    433: 
                    434:        port = Cvar_VariableValue ("qport");
                    435:        userinfo_modified = false;
                    436: 
                    437:        Netchan_OutOfBandPrint (NS_CLIENT, adr, "connect %i %i %i \"%s\"\n",
                    438:                PROTOCOL_VERSION, port, cls.challenge, Cvar_Userinfo() );
                    439: }
                    440: 
                    441: /*
                    442: =================
                    443: CL_CheckForResend
1.1.1.2   root      444: 
1.1       root      445: Resend a connect message if the last one has timed out
                    446: =================
                    447: */
                    448: void CL_CheckForResend (void)
                    449: {
                    450:        netadr_t        adr;
                    451: 
                    452:        // if the local server is running and we aren't
                    453:        // then connect
                    454:        if (cls.state == ca_disconnected && Com_ServerState() )
                    455:        {
                    456:                cls.state = ca_connecting;
                    457:                strncpy (cls.servername, "localhost", sizeof(cls.servername)-1);
                    458:                // we don't need a challenge on the localhost
                    459:                CL_SendConnectPacket ();
                    460:                return;
                    461: //             cls.connect_time = -99999;      // CL_CheckForResend() will fire immediately
                    462:        }
1.1.1.2   root      463: 
1.1       root      464:        // resend if we haven't gotten a reply yet
                    465:        if (cls.state != ca_connecting)
                    466:                return;
1.1.1.2   root      467: 
1.1       root      468:        if (cls.realtime - cls.connect_time < 3000)
                    469:                return;
                    470: 
                    471:        if (!NET_StringToAdr (cls.servername, &adr))
                    472:        {
                    473:                Com_Printf ("Bad server address\n");
                    474:                cls.state = ca_disconnected;
                    475:                return;
                    476:        }
                    477:        if (adr.port == 0)
                    478:                adr.port = BigShort (PORT_SERVER);
                    479: 
                    480:        cls.connect_time = cls.realtime;        // for retransmit requests
                    481: 
                    482:        Com_Printf ("Connecting to %s...\n", cls.servername);
                    483: 
                    484:        Netchan_OutOfBandPrint (NS_CLIENT, adr, "getchallenge\n");
                    485: }
1.1.1.2   root      486: 
                    487: 
1.1       root      488: /*
                    489: ================
                    490: CL_Connect_f
1.1.1.2   root      491: 
1.1       root      492: ================
                    493: */
                    494: void CL_Connect_f (void)
                    495: {
                    496:        char    *server;
1.1.1.2   root      497: 
1.1       root      498:        if (Cmd_Argc() != 2)
                    499:        {
                    500:                Com_Printf ("usage: connect <server>\n");
                    501:                return; 
                    502:        }
                    503:        
                    504:        if (Com_ServerState ())
                    505:        {       // if running a local server, kill it and reissue
                    506:                SV_Shutdown (va("Server quit\n", msg), false);
                    507:        }
                    508:        else
                    509:        {
                    510:                CL_Disconnect ();
                    511:        }
1.1.1.2   root      512: 
1.1       root      513:        server = Cmd_Argv (1);
1.1.1.2   root      514: 
1.1       root      515:        NET_Config (true);              // allow remote
1.1.1.2   root      516: 
1.1       root      517:        CL_Disconnect ();
1.1.1.2   root      518: 
1.1       root      519:        cls.state = ca_connecting;
                    520:        strncpy (cls.servername, server, sizeof(cls.servername)-1);
                    521:        cls.connect_time = -99999;      // CL_CheckForResend() will fire immediately
                    522: }
1.1.1.2   root      523: 
                    524: 
1.1       root      525: /*
                    526: =====================
                    527: CL_Rcon_f
1.1.1.2   root      528: 
1.1       root      529:   Send the rest of the command line over as
                    530:   an unconnected command.
                    531: =====================
                    532: */
                    533: void CL_Rcon_f (void)
                    534: {
                    535:        char    message[1024];
                    536:        int             i;
                    537:        netadr_t        to;
1.1.1.2   root      538: 
1.1       root      539:        if (!rcon_client_password->string)
                    540:        {
                    541:                Com_Printf ("You must set 'rcon_password' before\n"
                    542:                                        "issuing an rcon command.\n");
                    543:                return;
                    544:        }
1.1.1.2   root      545: 
1.1       root      546:        message[0] = (char)255;
                    547:        message[1] = (char)255;
                    548:        message[2] = (char)255;
                    549:        message[3] = (char)255;
                    550:        message[4] = 0;
                    551: 
                    552:        NET_Config (true);              // allow remote
1.1.1.2   root      553: 
1.1       root      554:        strcat (message, "rcon ");
1.1.1.2   root      555: 
1.1       root      556:        strcat (message, rcon_client_password->string);
                    557:        strcat (message, " ");
1.1.1.2   root      558: 
1.1       root      559:        for (i=1 ; i<Cmd_Argc() ; i++)
                    560:        {
                    561:                strcat (message, Cmd_Argv(i));
                    562:                strcat (message, " ");
                    563:        }
1.1.1.2   root      564: 
1.1       root      565:        if (cls.state >= ca_connected)
                    566:                to = cls.netchan.remote_address;
                    567:        else
                    568:        {
                    569:                if (!strlen(rcon_address->string))
                    570:                {
                    571:                        Com_Printf ("You must either be connected,\n"
                    572:                                                "or set the 'rcon_address' cvar\n"
                    573:                                                "to issue rcon commands\n");
1.1.1.2   root      574: 
1.1       root      575:                        return;
                    576:                }
                    577:                NET_StringToAdr (rcon_address->string, &to);
                    578:                if (to.port == 0)
                    579:                        to.port = BigShort (PORT_SERVER);
                    580:        }
                    581:        
                    582:        NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to);
                    583: }
1.1.1.2   root      584: 
                    585: 
1.1       root      586: /*
                    587: =====================
                    588: CL_ClearState
1.1.1.2   root      589: 
1.1       root      590: =====================
                    591: */
                    592: void CL_ClearState (void)
                    593: {
                    594:        S_StopAllSounds ();
                    595:        CL_ClearEffects ();
                    596:        CL_ClearTEnts ();
1.1.1.2   root      597: 
1.1       root      598: // wipe the entire cl structure
                    599:        memset (&cl, 0, sizeof(cl));
                    600:        memset (&cl_entities, 0, sizeof(cl_entities));
1.1.1.2   root      601: 
1.1       root      602:        SZ_Clear (&cls.netchan.message);
1.1.1.2   root      603: 
1.1       root      604: }
1.1.1.2   root      605: 
1.1       root      606: /*
                    607: =====================
                    608: CL_Disconnect
1.1.1.2   root      609: 
1.1       root      610: Goes from a connected state to full screen console state
                    611: Sends a disconnect message to the server
                    612: This is also called on Com_Error, so it shouldn't cause any errors
                    613: =====================
                    614: */
                    615: void CL_Disconnect (void)
                    616: {
                    617:        byte    final[32];
1.1.1.2   root      618: 
1.1       root      619:        if (cls.state == ca_disconnected)
                    620:                return;
1.1.1.2   root      621: 
1.1       root      622:        if (cl_timedemo && cl_timedemo->value)
                    623:        {
                    624:                int     time;
                    625:                
                    626:                time = Sys_Milliseconds () - cl.timedemo_start;
                    627:                if (time > 0)
                    628:                        Com_Printf ("%i frames, %3.1f seconds: %3.1f fps\n", cl.timedemo_frames,
                    629:                        time/1000.0, cl.timedemo_frames*1000.0 / time);
                    630:        }
1.1.1.2   root      631: 
1.1       root      632:        VectorClear (cl.refdef.blend);
                    633:        re.CinematicSetPalette(NULL);
                    634: 
                    635:        M_ForceMenuOff ();
1.1.1.2   root      636: 
1.1       root      637:        cls.connect_time = 0;
1.1.1.2   root      638: 
1.1       root      639:        SCR_StopCinematic ();
1.1.1.2   root      640: 
1.1       root      641:        if (cls.demorecording)
                    642:                CL_Stop_f ();
1.1.1.2   root      643: 
1.1       root      644:        // send a disconnect message to the server
                    645:        final[0] = clc_stringcmd;
                    646:        strcpy ((char *)final+1, "disconnect");
                    647:        Netchan_Transmit (&cls.netchan, strlen(final), final);
                    648:        Netchan_Transmit (&cls.netchan, strlen(final), final);
                    649:        Netchan_Transmit (&cls.netchan, strlen(final), final);
1.1.1.2   root      650: 
1.1       root      651:        CL_ClearState ();
1.1.1.2   root      652: 
                    653:        // stop download
                    654:        if (cls.download) {
                    655:                fclose(cls.download);
                    656:                cls.download = NULL;
                    657:        }
                    658: 
1.1       root      659:        cls.state = ca_disconnected;
                    660: }
1.1.1.2   root      661: 
1.1       root      662: void CL_Disconnect_f (void)
                    663: {
                    664:        Com_Error (ERR_DROP, "Disconnected from server");
                    665: }
1.1.1.2   root      666: 
                    667: 
1.1       root      668: /*
                    669: ====================
                    670: CL_Packet_f
1.1.1.2   root      671: 
1.1       root      672: packet <destination> <contents>
1.1.1.2   root      673: 
1.1       root      674: Contents allows \n escape character
                    675: ====================
                    676: */
                    677: void CL_Packet_f (void)
                    678: {
                    679:        char    send[2048];
                    680:        int             i, l;
                    681:        char    *in, *out;
                    682:        netadr_t        adr;
1.1.1.2   root      683: 
1.1       root      684:        if (Cmd_Argc() != 3)
                    685:        {
                    686:                Com_Printf ("packet <destination> <contents>\n");
                    687:                return;
                    688:        }
1.1.1.2   root      689: 
1.1       root      690:        NET_Config (true);              // allow remote
1.1.1.2   root      691: 
1.1       root      692:        if (!NET_StringToAdr (Cmd_Argv(1), &adr))
                    693:        {
                    694:                Com_Printf ("Bad address\n");
                    695:                return;
                    696:        }
                    697:        if (!adr.port)
                    698:                adr.port = BigShort (PORT_SERVER);
1.1.1.2   root      699: 
1.1       root      700:        in = Cmd_Argv(2);
                    701:        out = send+4;
                    702:        send[0] = send[1] = send[2] = send[3] = (char)0xff;
1.1.1.2   root      703: 
1.1       root      704:        l = strlen (in);
                    705:        for (i=0 ; i<l ; i++)
                    706:        {
                    707:                if (in[i] == '\\' && in[i+1] == 'n')
                    708:                {
                    709:                        *out++ = '\n';
                    710:                        i++;
                    711:                }
                    712:                else
                    713:                        *out++ = in[i];
                    714:        }
                    715:        *out = 0;
1.1.1.2   root      716: 
1.1       root      717:        NET_SendPacket (NS_CLIENT, out-send, send, adr);
                    718: }
1.1.1.2   root      719: 
1.1       root      720: /*
                    721: =================
                    722: CL_Changing_f
1.1.1.2   root      723: 
1.1       root      724: Just sent as a hint to the client that they should
                    725: drop to full console
                    726: =================
                    727: */
                    728: void CL_Changing_f (void)
                    729: {
1.1.1.2   root      730:        //ZOID
                    731:        //if we are downloading, we don't change!  This so we don't suddenly stop downloading a map
                    732:        if (cls.download)
                    733:                return;
                    734: 
1.1       root      735:        SCR_BeginLoadingPlaque ();
                    736:        cls.state = ca_connected;       // not active anymore, but not disconnected
                    737:        Com_Printf ("\nChanging map...\n");
                    738: }
1.1.1.2   root      739: 
                    740: 
1.1       root      741: /*
                    742: =================
                    743: CL_Reconnect_f
1.1.1.2   root      744: 
1.1       root      745: The server is changing levels
                    746: =================
                    747: */
                    748: void CL_Reconnect_f (void)
                    749: {
1.1.1.2   root      750:        //ZOID
                    751:        //if we are downloading, we don't change!  This so we don't suddenly stop downloading a map
                    752:        if (cls.download)
                    753:                return;
                    754: 
1.1       root      755:        S_StopAllSounds ();
1.1.1.2   root      756:        if (cls.state == ca_connected) {
                    757:                Com_Printf ("reconnecting...\n");
                    758:                cls.state = ca_connected;
                    759:                MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
                    760:                MSG_WriteString (&cls.netchan.message, "new");          
                    761:                return;
                    762:        }
                    763: 
                    764:        if (*cls.servername) {
                    765:                if (cls.state >= ca_connected) {
                    766:                        CL_Disconnect();
                    767:                        cls.connect_time = cls.realtime - 1500;
                    768:                } else
                    769:                        cls.connect_time = -99999; // fire immediately
                    770: 
                    771:                cls.state = ca_connecting;
                    772:                Com_Printf ("reconnecting...\n");
                    773:        }
1.1       root      774: }
1.1.1.2   root      775: 
1.1       root      776: /*
                    777: =================
                    778: CL_ParseStatusMessage
1.1.1.2   root      779: 
1.1       root      780: Handle a reply from a ping
                    781: =================
                    782: */
                    783: void CL_ParseStatusMessage (void)
                    784: {
                    785:        char    *s;
                    786: 
                    787:        s = MSG_ReadString(&net_message);
1.1.1.2   root      788: 
1.1       root      789:        Com_Printf ("%s\n", s);
                    790:        M_AddToServerList (net_from, s);
                    791: }
1.1.1.2   root      792: 
                    793: 
1.1       root      794: /*
                    795: =================
                    796: CL_PingServers_f
                    797: =================
                    798: */
                    799: void CL_PingServers_f (void)
                    800: {
                    801:        int                     i;
                    802:        netadr_t        adr;
                    803:        char            name[32];
                    804:        char            *adrstring;
                    805:        cvar_t          *noudp;
                    806:        cvar_t          *noipx;
1.1.1.2   root      807: 
1.1       root      808:        NET_Config (true);              // allow remote
1.1.1.2   root      809: 
1.1       root      810:        // send a broadcast packet
                    811:        Com_Printf ("pinging broadcast...\n");
                    812: 
                    813:        noudp = Cvar_Get ("noudp", "0", CVAR_NOSET);
                    814:        if (!noudp->value)
                    815:        {
                    816:                adr.type = NA_BROADCAST;
                    817:                adr.port = BigShort(PORT_SERVER);
                    818:                Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
                    819:        }
                    820: 
                    821:        noipx = Cvar_Get ("noipx", "0", CVAR_NOSET);
                    822:        if (!noipx->value)
                    823:        {
                    824:                adr.type = NA_BROADCAST_IPX;
                    825:                adr.port = BigShort(PORT_SERVER);
                    826:                Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
                    827:        }
1.1.1.2   root      828: 
1.1       root      829:        // send a packet to each address book entry
                    830:        for (i=0 ; i<16 ; i++)
                    831:        {
                    832:                Com_sprintf (name, sizeof(name), "adr%i", i);
                    833:                adrstring = Cvar_VariableString (name);
                    834:                if (!adrstring || !adrstring[0])
                    835:                        continue;
1.1.1.2   root      836: 
1.1       root      837:                Com_Printf ("pinging %s...\n", adrstring);
                    838:                if (!NET_StringToAdr (adrstring, &adr))
                    839:                {
                    840:                        Com_Printf ("Bad address: %s\n", adrstring);
                    841:                        continue;
                    842:                }
                    843:                if (!adr.port)
                    844:                        adr.port = BigShort(PORT_SERVER);
                    845:                Netchan_OutOfBandPrint (NS_CLIENT, adr, va("info %i", PROTOCOL_VERSION));
                    846:        }
                    847: }
                    848: 
1.1.1.2   root      849: 
1.1       root      850: /*
                    851: =================
                    852: CL_Skins_f
                    853: 
                    854: Load or download any custom player skins and models
                    855: =================
                    856: */
                    857: void CL_Skins_f (void)
                    858: {
                    859:        int             i;
                    860: 
                    861:        for (i=0 ; i<MAX_CLIENTS ; i++)
                    862:        {
                    863:                if (!cl.configstrings[CS_PLAYERSKINS+i][0])
                    864:                        continue;
                    865:                Com_Printf ("client %i: %s\n", i, cl.configstrings[CS_PLAYERSKINS+i]); 
                    866:                SCR_UpdateScreen ();
                    867:                Sys_SendKeyEvents ();   // pump message loop
                    868:                CL_ParseClientinfo (i);
                    869:        }
                    870: }
                    871: 
1.1.1.2   root      872: 
1.1       root      873: /*
                    874: =================
                    875: CL_ConnectionlessPacket
1.1.1.2   root      876: 
1.1       root      877: Responses to broadcasts, etc
                    878: =================
                    879: */
                    880: void CL_ConnectionlessPacket (void)
                    881: {
                    882:        char    *s;
                    883:        char    *c;
                    884:        
                    885:        MSG_BeginReading (&net_message);
                    886:        MSG_ReadLong (&net_message);    // skip the -1
1.1.1.2   root      887: 
1.1       root      888:        s = MSG_ReadStringLine (&net_message);
1.1.1.2   root      889: 
1.1       root      890:        Cmd_TokenizeString (s, false);
1.1.1.2   root      891: 
1.1       root      892:        c = Cmd_Argv(0);
1.1.1.2   root      893: 
1.1       root      894:        Com_Printf ("%s: %s\n", NET_AdrToString (net_from), c);
1.1.1.2   root      895: 
1.1       root      896:        // server connection
                    897:        if (!strcmp(c, "client_connect"))
                    898:        {
                    899:                if (cls.state == ca_connected)
                    900:                {
                    901:                        Com_Printf ("Dup connect received.  Ignored.\n");
                    902:                        return;
                    903:                }
                    904:                Netchan_Setup (NS_CLIENT, &cls.netchan, net_from, cls.quakePort);
                    905:                MSG_WriteChar (&cls.netchan.message, clc_stringcmd);
                    906:                MSG_WriteString (&cls.netchan.message, "new");  
                    907:                cls.state = ca_connected;
                    908:                return;
                    909:        }
1.1.1.2   root      910: 
1.1       root      911:        // server responding to a status broadcast
                    912:        if (!strcmp(c, "info"))
                    913:        {
                    914:                CL_ParseStatusMessage ();
                    915:                return;
                    916:        }
1.1.1.2   root      917: 
1.1       root      918:        // remote command from gui front end
                    919:        if (!strcmp(c, "cmd"))
                    920:        {
                    921:                if (!NET_IsLocalAddress(net_from))
                    922:                {
                    923:                        Com_Printf ("Command packet from remote host.  Ignored.\n");
                    924:                        return;
                    925:                }
                    926:                Sys_AppActivate ();
                    927:                s = MSG_ReadString (&net_message);
                    928:                Cbuf_AddText (s);
                    929:                Cbuf_AddText ("\n");
                    930:                return;
                    931:        }
                    932:        // print command from somewhere
                    933:        if (!strcmp(c, "print"))
                    934:        {
                    935:                s = MSG_ReadString (&net_message);
1.1.1.3   root      936:                Com_Printf ("%s", s);
1.1       root      937:                return;
                    938:        }
1.1.1.2   root      939: 
1.1       root      940:        // ping from somewhere
                    941:        if (!strcmp(c, "ping"))
                    942:        {
                    943:                Netchan_OutOfBandPrint (NS_CLIENT, net_from, "ack");
                    944:                return;
                    945:        }
                    946: 
                    947:        // challenge from the server we are connecting to
                    948:        if (!strcmp(c, "challenge"))
                    949:        {
                    950:                cls.challenge = atoi(Cmd_Argv(1));
                    951:                CL_SendConnectPacket ();
                    952:                return;
                    953:        }
                    954: 
                    955:        // echo request from server
                    956:        if (!strcmp(c, "echo"))
                    957:        {
                    958:                Netchan_OutOfBandPrint (NS_CLIENT, net_from, "%s", Cmd_Argv(1) );
                    959:                return;
                    960:        }
                    961: 
                    962:        Com_Printf ("Unknown command.\n");
                    963: }
1.1.1.2   root      964: 
                    965: 
1.1       root      966: /*
                    967: =================
                    968: CL_DumpPackets
                    969: 
                    970: A vain attempt to help bad TCP stacks that cause problems
                    971: when they overflow
                    972: =================
                    973: */
                    974: void CL_DumpPackets (void)
                    975: {
                    976:        while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
                    977:        {
                    978:                Com_Printf ("dumnping a packet\n");
                    979:        }
                    980: }
1.1.1.2   root      981: 
1.1       root      982: /*
                    983: =================
                    984: CL_ReadPackets
                    985: =================
                    986: */
                    987: void CL_ReadPackets (void)
                    988: {
                    989:        while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
                    990:        {
                    991: //     Com_Printf ("packet\n");
                    992:                //
                    993:                // remote command packet
                    994:                //
                    995:                if (*(int *)net_message.data == -1)
                    996:                {
                    997:                        CL_ConnectionlessPacket ();
                    998:                        continue;
                    999:                }
1.1.1.2   root     1000: 
1.1       root     1001:                if (cls.state == ca_disconnected || cls.state == ca_connecting)
                   1002:                        continue;               // dump it if not connected
1.1.1.2   root     1003: 
1.1       root     1004:                if (net_message.cursize < 8)
                   1005:                {
                   1006:                        Com_Printf ("%s: Runt packet\n",NET_AdrToString(net_from));
                   1007:                        continue;
                   1008:                }
1.1.1.2   root     1009: 
1.1       root     1010:                //
                   1011:                // packet from server
                   1012:                //
                   1013:                if (!NET_CompareAdr (net_from, cls.netchan.remote_address))
                   1014:                {
                   1015:                        Com_DPrintf ("%s:sequenced packet without connection\n"
                   1016:                                ,NET_AdrToString(net_from));
                   1017:                        continue;
                   1018:                }
                   1019:                if (!Netchan_Process(&cls.netchan, &net_message))
                   1020:                        continue;               // wasn't accepted for some reason
                   1021:                CL_ParseServerMessage ();
                   1022:        }
1.1.1.2   root     1023: 
1.1       root     1024:        //
                   1025:        // check timeout
                   1026:        //
                   1027:        if (cls.state >= ca_connected
                   1028:         && cls.realtime - cls.netchan.last_received > cl_timeout->value*1000)
                   1029:        {
                   1030:                if (++cl.timeoutcount > 5)      // timeoutcount saves debugger
                   1031:                {
                   1032:                        Com_Printf ("\nServer connection timed out.\n");
                   1033:                        CL_Disconnect ();
                   1034:                        return;
                   1035:                }
                   1036:        }
                   1037:        else
                   1038:                cl.timeoutcount = 0;
                   1039:        
                   1040: }
1.1.1.2   root     1041: 
                   1042: 
1.1       root     1043: //=============================================================================
1.1.1.2   root     1044: 
                   1045: /*
                   1046: ==============
                   1047: CL_FixUpGender_f
                   1048: ==============
                   1049: */
                   1050: void CL_FixUpGender(void)
                   1051: {
                   1052:        char *p;
                   1053:        char sk[80];
                   1054: 
                   1055:        if (gender_auto->value) {
                   1056: 
                   1057:                if (gender->modified) {
                   1058:                        // was set directly, don't override the user
                   1059:                        gender->modified = false;
                   1060:                        return;
                   1061:                }
                   1062: 
                   1063:                strncpy(sk, skin->string, sizeof(sk) - 1);
                   1064:                if ((p = strchr(sk, '/')) != NULL)
                   1065:                        *p = 0;
                   1066:                if (Q_stricmp(sk, "male") == 0 || Q_stricmp(sk, "cyborg") == 0)
                   1067:                        Cvar_Set ("gender", "male");
                   1068:                else if (Q_stricmp(sk, "female") == 0 || Q_stricmp(sk, "crackhor") == 0)
                   1069:                        Cvar_Set ("gender", "female");
                   1070:                else
                   1071:                        Cvar_Set ("gender", "none");
                   1072:                gender->modified = false;
                   1073:        }
                   1074: }
                   1075: 
1.1       root     1076: /*
                   1077: ==============
                   1078: CL_Userinfo_f
                   1079: ==============
                   1080: */
                   1081: void CL_Userinfo_f (void)
                   1082: {
                   1083:        Com_Printf ("User info settings:\n");
                   1084:        Info_Print (Cvar_Userinfo());
                   1085: }
1.1.1.2   root     1086: 
1.1       root     1087: /*
                   1088: =================
                   1089: CL_Snd_Restart_f
1.1.1.2   root     1090: 
1.1       root     1091: Restart the sound subsystem so it can pick up
                   1092: new parameters and flush all sounds
                   1093: =================
                   1094: */
                   1095: void CL_Snd_Restart_f (void)
                   1096: {
                   1097:        S_Shutdown ();
                   1098:        S_Init ();
                   1099:        CL_RegisterSounds ();
                   1100: }
1.1.1.2   root     1101: 
                   1102: int precache_check; // for autodownload of precache items
                   1103: int precache_spawncount;
                   1104: int precache_tex;
                   1105: int precache_model_skin;
                   1106: 
                   1107: byte *precache_model; // used for skin checking in alias models
                   1108: 
                   1109: #define PLAYER_MULT 5
                   1110: 
1.1.1.3   root     1111: // ENV_CNT is map load, ENV_CNT+1 is first env map
                   1112: #define ENV_CNT (CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT)
                   1113: #define TEXTURE_CNT (ENV_CNT+13)
                   1114: 
                   1115: static const char *env_suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
1.1.1.2   root     1116: 
                   1117: void CL_RequestNextDownload (void)
                   1118: {
                   1119:        unsigned        map_checksum;           // for detecting cheater maps
                   1120:        char fn[MAX_OSPATH];
                   1121:        dmdl_t *pheader;
                   1122: 
                   1123:        if (cls.state != ca_connected)
                   1124:                return;
                   1125: 
1.1.1.3   root     1126:        if (!allow_download->value && precache_check < ENV_CNT)
                   1127:                precache_check = ENV_CNT;
1.1.1.2   root     1128: 
                   1129: //ZOID
                   1130:        if (precache_check == CS_MODELS) { // confirm map
                   1131:                precache_check = CS_MODELS+2; // 0 isn't used
                   1132:                if (allow_download_maps->value)
                   1133:                        if (!CL_CheckOrDownloadFile(cl.configstrings[CS_MODELS+1]))
                   1134:                                return; // started a download
                   1135:        }
                   1136:        if (precache_check >= CS_MODELS && precache_check < CS_MODELS+MAX_MODELS) {
                   1137:                if (allow_download_models->value) {
                   1138:                        while (precache_check < CS_MODELS+MAX_MODELS &&
                   1139:                                cl.configstrings[precache_check][0]) {
                   1140:                                if (cl.configstrings[precache_check][0] == '*' ||
                   1141:                                        cl.configstrings[precache_check][0] == '#') {
                   1142:                                        precache_check++;
                   1143:                                        continue;
                   1144:                                }
                   1145:                                if (precache_model_skin == 0) {
                   1146:                                        if (!CL_CheckOrDownloadFile(cl.configstrings[precache_check])) {
                   1147:                                                precache_model_skin = 1;
                   1148:                                                return; // started a download
                   1149:                                        }
                   1150:                                        precache_model_skin = 1;
                   1151:                                }
                   1152: 
                   1153:                                // checking for skins in the model
                   1154:                                if (!precache_model) {
                   1155: 
                   1156:                                        FS_LoadFile (cl.configstrings[precache_check], (void **)&precache_model);
                   1157:                                        if (!precache_model) {
                   1158:                                                precache_model_skin = 0;
                   1159:                                                precache_check++;
                   1160:                                                continue; // couldn't load it
                   1161:                                        }
                   1162:                                        if (LittleLong(*(unsigned *)precache_model) != IDALIASHEADER) {
                   1163:                                                // not an alias model
                   1164:                                                FS_FreeFile(precache_model);
                   1165:                                                precache_model = 0;
                   1166:                                                precache_model_skin = 0;
                   1167:                                                precache_check++;
                   1168:                                                continue;
                   1169:                                        }
                   1170:                                        pheader = (dmdl_t *)precache_model;
                   1171:                                        if (LittleLong (pheader->version) != ALIAS_VERSION) {
                   1172:                                                precache_check++;
                   1173:                                                precache_model_skin = 0;
                   1174:                                                continue; // couldn't load it
                   1175:                                        }
                   1176:                                }
                   1177: 
                   1178:                                pheader = (dmdl_t *)precache_model;
                   1179: 
                   1180:                                while (precache_model_skin - 1 < LittleLong(pheader->num_skins)) {
                   1181:                                        if (!CL_CheckOrDownloadFile((char *)precache_model +
                   1182:                                                LittleLong(pheader->ofs_skins) + 
                   1183:                                                (precache_model_skin - 1)*MAX_SKINNAME)) {
                   1184:                                                precache_model_skin++;
                   1185:                                                return; // started a download
                   1186:                                        }
                   1187:                                        precache_model_skin++;
                   1188:                                }
                   1189:                                if (precache_model) { 
                   1190:                                        FS_FreeFile(precache_model);
                   1191:                                        precache_model = 0;
                   1192:                                }
                   1193:                                precache_model_skin = 0;
                   1194:                                precache_check++;
                   1195:                        }
                   1196:                }
                   1197:                precache_check = CS_SOUNDS;
                   1198:        }
                   1199:        if (precache_check >= CS_SOUNDS && precache_check < CS_SOUNDS+MAX_SOUNDS) { 
                   1200:                if (allow_download_sounds->value) {
                   1201:                        if (precache_check == CS_SOUNDS)
                   1202:                                precache_check++; // zero is blank
                   1203:                        while (precache_check < CS_SOUNDS+MAX_SOUNDS &&
                   1204:                                cl.configstrings[precache_check][0]) {
                   1205:                                if (cl.configstrings[precache_check][0] == '*') {
                   1206:                                        precache_check++;
                   1207:                                        continue;
                   1208:                                }
                   1209:                                Com_sprintf(fn, sizeof(fn), "sound/%s", cl.configstrings[precache_check++]);
                   1210:                                if (!CL_CheckOrDownloadFile(fn))
                   1211:                                        return; // started a download
                   1212:                        }
                   1213:                }
                   1214:                precache_check = CS_IMAGES;
                   1215:        }
                   1216:        if (precache_check >= CS_IMAGES && precache_check < CS_IMAGES+MAX_IMAGES) {
                   1217:                if (precache_check == CS_IMAGES)
                   1218:                        precache_check++; // zero is blank
                   1219:                while (precache_check < CS_IMAGES+MAX_IMAGES &&
                   1220:                        cl.configstrings[precache_check][0]) {
                   1221:                        Com_sprintf(fn, sizeof(fn), "pics/%s.pcx", cl.configstrings[precache_check++]);
                   1222:                        if (!CL_CheckOrDownloadFile(fn))
                   1223:                                return; // started a download
                   1224:                }
                   1225:                precache_check = CS_PLAYERSKINS;
                   1226:        }
                   1227:        // skins are special, since a player has three things to download:
                   1228:        // model, weapon model and skin
                   1229:        // so precache_check is now *3
                   1230:        if (precache_check >= CS_PLAYERSKINS && precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) {
                   1231:                if (allow_download_players->value) {
                   1232:                        while (precache_check < CS_PLAYERSKINS + MAX_CLIENTS * PLAYER_MULT) {
                   1233:                                int i, n;
                   1234:                                char model[MAX_QPATH], skin[MAX_QPATH], *p;
                   1235: 
                   1236:                                i = (precache_check - CS_PLAYERSKINS)/PLAYER_MULT;
                   1237:                                n = (precache_check - CS_PLAYERSKINS)%PLAYER_MULT;
                   1238: 
                   1239:                                if (!cl.configstrings[CS_PLAYERSKINS+i][0]) {
                   1240:                                        precache_check = CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
                   1241:                                        continue;
                   1242:                                }
                   1243: 
                   1244:                                if ((p = strchr(cl.configstrings[CS_PLAYERSKINS+i], '\\')) != NULL)
                   1245:                                        p++;
                   1246:                                else
                   1247:                                        p = cl.configstrings[CS_PLAYERSKINS+i];
                   1248:                                strcpy(model, p);
                   1249:                                p = strchr(model, '/');
                   1250:                                if (!p)
                   1251:                                        p = strchr(model, '\\');
                   1252:                                if (p) {
                   1253:                                        *p++ = 0;
                   1254:                                        strcpy(skin, p);
                   1255:                                } else
                   1256:                                        *skin = 0;
                   1257: 
                   1258:                                switch (n) {
                   1259:                                case 0: // model
                   1260:                                        Com_sprintf(fn, sizeof(fn), "players/%s/tris.md2", model);
                   1261:                                        if (!CL_CheckOrDownloadFile(fn)) {
                   1262:                                                precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 1;
                   1263:                                                return; // started a download
                   1264:                                        }
                   1265:                                        n++;
                   1266:                                        /*FALL THROUGH*/
                   1267: 
                   1268:                                case 1: // weapon model
                   1269:                                        Com_sprintf(fn, sizeof(fn), "players/%s/weapon.md2", model);
                   1270:                                        if (!CL_CheckOrDownloadFile(fn)) {
                   1271:                                                precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 2;
                   1272:                                                return; // started a download
                   1273:                                        }
                   1274:                                        n++;
                   1275:                                        /*FALL THROUGH*/
                   1276: 
                   1277:                                case 2: // weapon skin
                   1278:                                        Com_sprintf(fn, sizeof(fn), "players/%s/weapon.pcx", model);
                   1279:                                        if (!CL_CheckOrDownloadFile(fn)) {
                   1280:                                                precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 3;
                   1281:                                                return; // started a download
                   1282:                                        }
                   1283:                                        n++;
                   1284:                                        /*FALL THROUGH*/
                   1285: 
                   1286:                                case 3: // skin
                   1287:                                        Com_sprintf(fn, sizeof(fn), "players/%s/%s.pcx", model, skin);
                   1288:                                        if (!CL_CheckOrDownloadFile(fn)) {
                   1289:                                                precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 4;
                   1290:                                                return; // started a download
                   1291:                                        }
                   1292:                                        n++;
                   1293:                                        /*FALL THROUGH*/
                   1294: 
                   1295:                                case 4: // skin_i
                   1296:                                        Com_sprintf(fn, sizeof(fn), "players/%s/%s_i.pcx", model, skin);
                   1297:                                        if (!CL_CheckOrDownloadFile(fn)) {
                   1298:                                                precache_check = CS_PLAYERSKINS + i * PLAYER_MULT + 5;
                   1299:                                                return; // started a download
                   1300:                                        }
                   1301:                                        // move on to next model
                   1302:                                        precache_check = CS_PLAYERSKINS + (i + 1) * PLAYER_MULT;
                   1303:                                }
                   1304:                        }
                   1305:                }
                   1306:                // precache phase completed
1.1.1.3   root     1307:                precache_check = ENV_CNT;
1.1.1.2   root     1308:        }
                   1309: 
1.1.1.3   root     1310:        if (precache_check == ENV_CNT) {
                   1311:                precache_check = ENV_CNT + 1;
1.1.1.2   root     1312: 
                   1313:                CM_LoadMap (cl.configstrings[CS_MODELS+1], true, &map_checksum);
                   1314: 
1.1.1.3   root     1315:                if (map_checksum != atoi(cl.configstrings[CS_MAPCHECKSUM])) {
1.1.1.2   root     1316:                        Com_Error (ERR_DROP, "Local map version differs from server: %i != '%s'\n",
1.1.1.3   root     1317:                                map_checksum, cl.configstrings[CS_MAPCHECKSUM]);
                   1318:                        return;
                   1319:                }
                   1320:        }
                   1321: 
                   1322:        if (precache_check > ENV_CNT && precache_check < TEXTURE_CNT) {
                   1323:                if (allow_download->value && allow_download_maps->value) {
                   1324:                        while (precache_check < TEXTURE_CNT) {
                   1325:                                int n = precache_check++ - ENV_CNT - 1;
                   1326: 
                   1327:                                if (n & 1)
                   1328:                                        Com_sprintf(fn, sizeof(fn), "env/%s%s.pcx", 
                   1329:                                                cl.configstrings[CS_SKY], env_suf[n/2]);
                   1330:                                else
                   1331:                                        Com_sprintf(fn, sizeof(fn), "env/%s%s.tga", 
                   1332:                                                cl.configstrings[CS_SKY], env_suf[n/2]);
                   1333:                                if (!CL_CheckOrDownloadFile(fn))
                   1334:                                        return; // started a download
                   1335:                        }
                   1336:                }
                   1337:                precache_check = TEXTURE_CNT;
                   1338:        }
                   1339: 
                   1340:        if (precache_check == TEXTURE_CNT) {
                   1341:                precache_check = TEXTURE_CNT+1;
                   1342:                precache_tex = 0;
1.1.1.2   root     1343:        }
                   1344: 
                   1345:        // confirm existance of textures, download any that don't exist
                   1346:        if (precache_check == TEXTURE_CNT+1) {
                   1347:                // from qcommon/cmodel.c
                   1348:                extern int                      numtexinfo;
                   1349:                extern mapsurface_t     map_surfaces[];
                   1350: 
                   1351:                if (allow_download->value && allow_download_maps->value) {
                   1352:                        while (precache_tex < numtexinfo) {
                   1353:                                char fn[MAX_OSPATH];
                   1354: 
                   1355:                                sprintf(fn, "textures/%s.wal", map_surfaces[precache_tex++].rname);
                   1356:                                if (!CL_CheckOrDownloadFile(fn))
                   1357:                                        return; // started a download
                   1358:                        }
                   1359:                }
                   1360:                precache_check = TEXTURE_CNT+999;
                   1361:        }
                   1362: 
                   1363: //ZOID
                   1364:        CL_RegisterSounds ();
                   1365:        CL_PrepRefresh ();
                   1366: 
                   1367:        MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
                   1368:        MSG_WriteString (&cls.netchan.message, va("begin %i\n", precache_spawncount) );
                   1369: }
                   1370: 
1.1       root     1371: /*
                   1372: =================
                   1373: CL_Precache_f
1.1.1.2   root     1374: 
1.1       root     1375: The server will send this command right
                   1376: before allowing the client into the server
                   1377: =================
                   1378: */
                   1379: void CL_Precache_f (void)
                   1380: {
1.1.1.2   root     1381:        //Yet another hack to let old demos work
                   1382:        //the old precache sequence
                   1383:        if (Cmd_Argc() < 2) {
                   1384:                unsigned        map_checksum;           // for detecting cheater maps
1.1       root     1385: 
1.1.1.2   root     1386:                CM_LoadMap (cl.configstrings[CS_MODELS+1], true, &map_checksum);
                   1387:                CL_RegisterSounds ();
                   1388:                CL_PrepRefresh ();
                   1389:                return;
                   1390:        }
1.1       root     1391: 
1.1.1.2   root     1392:        precache_check = CS_MODELS;
                   1393:        precache_spawncount = atoi(Cmd_Argv(1));
                   1394:        precache_model = 0;
                   1395:        precache_model_skin = 0;
                   1396: 
                   1397:        CL_RequestNextDownload();
1.1       root     1398: }
1.1.1.2   root     1399: 
                   1400: 
1.1       root     1401: /*
                   1402: =================
                   1403: CL_InitLocal
                   1404: =================
                   1405: */
                   1406: void CL_InitLocal (void)
                   1407: {
                   1408:        cls.state = ca_disconnected;
                   1409:        cls.realtime = Sys_Milliseconds ();
1.1.1.2   root     1410: 
1.1       root     1411:        CL_InitInput ();
                   1412: 
                   1413:        adr0 = Cvar_Get( "adr0", "", CVAR_ARCHIVE );
                   1414:        adr1 = Cvar_Get( "adr1", "", CVAR_ARCHIVE );
                   1415:        adr2 = Cvar_Get( "adr2", "", CVAR_ARCHIVE );
                   1416:        adr3 = Cvar_Get( "adr3", "", CVAR_ARCHIVE );
                   1417:        adr4 = Cvar_Get( "adr4", "", CVAR_ARCHIVE );
                   1418:        adr5 = Cvar_Get( "adr5", "", CVAR_ARCHIVE );
                   1419:        adr6 = Cvar_Get( "adr6", "", CVAR_ARCHIVE );
                   1420:        adr7 = Cvar_Get( "adr7", "", CVAR_ARCHIVE );
                   1421:        adr8 = Cvar_Get( "adr8", "", CVAR_ARCHIVE );
1.1.1.2   root     1422: 
1.1       root     1423: //
                   1424: // register our variables
                   1425: //
                   1426:        cl_stereo_separation = Cvar_Get( "cl_stereo_separation", "0.4", CVAR_ARCHIVE );
                   1427:        cl_stereo = Cvar_Get( "cl_stereo", "0", 0 );
                   1428: 
                   1429:        cl_add_blend = Cvar_Get ("cl_blend", "1", 0);
                   1430:        cl_add_lights = Cvar_Get ("cl_lights", "1", 0);
                   1431:        cl_add_particles = Cvar_Get ("cl_particles", "1", 0);
                   1432:        cl_add_entities = Cvar_Get ("cl_entities", "1", 0);
                   1433:        cl_gun = Cvar_Get ("cl_gun", "1", 0);
                   1434:        cl_footsteps = Cvar_Get ("cl_footsteps", "1", 0);
                   1435:        cl_noskins = Cvar_Get ("cl_noskins", "0", 0);
                   1436:        cl_autoskins = Cvar_Get ("cl_autoskins", "0", 0);
                   1437:        cl_predict = Cvar_Get ("cl_predict", "1", 0);
1.1.1.2   root     1438: //     cl_minfps = Cvar_Get ("cl_minfps", "5", 0);
1.1       root     1439:        cl_maxfps = Cvar_Get ("cl_maxfps", "90", 0);
1.1.1.2   root     1440: 
1.1       root     1441:        cl_upspeed = Cvar_Get ("cl_upspeed", "200", 0);
                   1442:        cl_forwardspeed = Cvar_Get ("cl_forwardspeed", "200", 0);
                   1443:        cl_sidespeed = Cvar_Get ("cl_sidespeed", "200", 0);
                   1444:        cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", 0);
                   1445:        cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", 0);
                   1446:        cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", 0);
1.1.1.2   root     1447: 
1.1       root     1448:        cl_run = Cvar_Get ("cl_run", "0", CVAR_ARCHIVE);
                   1449:        freelook = Cvar_Get( "freelook", "0", CVAR_ARCHIVE );
                   1450:        lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE);
                   1451:        lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE);
                   1452:        sensitivity = Cvar_Get ("sensitivity", "3", CVAR_ARCHIVE);
                   1453: 
                   1454:        m_pitch = Cvar_Get ("m_pitch", "0.022", CVAR_ARCHIVE);
                   1455:        m_yaw = Cvar_Get ("m_yaw", "0.022", 0);
                   1456:        m_forward = Cvar_Get ("m_forward", "1", 0);
                   1457:        m_side = Cvar_Get ("m_side", "1", 0);
                   1458: 
                   1459:        cl_shownet = Cvar_Get ("cl_shownet", "0", 0);
                   1460:        cl_showmiss = Cvar_Get ("cl_showmiss", "0", 0);
                   1461:        cl_showclamp = Cvar_Get ("showclamp", "0", 0);
                   1462:        cl_timeout = Cvar_Get ("cl_timeout", "120", 0);
                   1463:        cl_paused = Cvar_Get ("paused", "0", 0);
                   1464:        cl_timedemo = Cvar_Get ("timedemo", "0", 0);
1.1.1.2   root     1465: 
1.1       root     1466:        rcon_client_password = Cvar_Get ("rcon_password", "", 0);
                   1467:        rcon_address = Cvar_Get ("rcon_address", "", 0);
1.1.1.2   root     1468: 
1.1       root     1469:        cl_lightlevel = Cvar_Get ("r_lightlevel", "0", 0);
1.1.1.2   root     1470: 
1.1       root     1471:        //
                   1472:        // userinfo
                   1473:        //
                   1474:        info_password = Cvar_Get ("password", "", CVAR_USERINFO);
1.1.1.3   root     1475:        info_spectator = Cvar_Get ("spectator", "0", CVAR_USERINFO);
1.1       root     1476:        name = Cvar_Get ("name", "unnamed", CVAR_USERINFO | CVAR_ARCHIVE);
                   1477:        skin = Cvar_Get ("skin", "male/grunt", CVAR_USERINFO | CVAR_ARCHIVE);
                   1478:        rate = Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE);        // FIXME
                   1479:        msg = Cvar_Get ("msg", "1", CVAR_USERINFO | CVAR_ARCHIVE);
                   1480:        hand = Cvar_Get ("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
                   1481:        fov = Cvar_Get ("fov", "90", CVAR_USERINFO | CVAR_ARCHIVE);
1.1.1.2   root     1482:        gender = Cvar_Get ("gender", "male", CVAR_USERINFO | CVAR_ARCHIVE);
                   1483:        gender_auto = Cvar_Get ("gender_auto", "1", CVAR_ARCHIVE);
                   1484:        gender->modified = false; // clear this so we know when user sets it manually
                   1485: 
                   1486:        cl_vwep = Cvar_Get ("cl_vwep", "1", CVAR_ARCHIVE);
                   1487: 
                   1488: 
1.1       root     1489:        //
                   1490:        // register our commands
                   1491:        //
                   1492:        Cmd_AddCommand ("cmd", CL_ForwardToServer_f);
                   1493:        Cmd_AddCommand ("pause", CL_Pause_f);
                   1494:        Cmd_AddCommand ("pingservers", CL_PingServers_f);
                   1495:        Cmd_AddCommand ("skins", CL_Skins_f);
1.1.1.2   root     1496: 
1.1       root     1497:        Cmd_AddCommand ("userinfo", CL_Userinfo_f);
                   1498:        Cmd_AddCommand ("snd_restart", CL_Snd_Restart_f);
1.1.1.2   root     1499: 
1.1       root     1500:        Cmd_AddCommand ("changing", CL_Changing_f);
                   1501:        Cmd_AddCommand ("disconnect", CL_Disconnect_f);
                   1502:        Cmd_AddCommand ("record", CL_Record_f);
                   1503:        Cmd_AddCommand ("stop", CL_Stop_f);
1.1.1.2   root     1504: 
1.1       root     1505:        Cmd_AddCommand ("quit", CL_Quit_f);
1.1.1.2   root     1506: 
1.1       root     1507:        Cmd_AddCommand ("connect", CL_Connect_f);
                   1508:        Cmd_AddCommand ("reconnect", CL_Reconnect_f);
1.1.1.2   root     1509: 
1.1       root     1510:        Cmd_AddCommand ("rcon", CL_Rcon_f);
                   1511: 
                   1512: //     Cmd_AddCommand ("packet", CL_Packet_f); // this is dangerous to leave in
1.1.1.2   root     1513: 
1.1       root     1514:        Cmd_AddCommand ("setenv", CL_Setenv_f );
1.1.1.2   root     1515: 
1.1       root     1516:        Cmd_AddCommand ("precache", CL_Precache_f);
1.1.1.2   root     1517: 
                   1518:        Cmd_AddCommand ("download", CL_Download_f);
                   1519: 
1.1       root     1520:        //
                   1521:        // forward to server commands
                   1522:        //
                   1523:        // the only thing this does is allow command completion
                   1524:        // to work -- all unknown commands are automatically
                   1525:        // forwarded to the server
                   1526:        Cmd_AddCommand ("wave", NULL);
                   1527:        Cmd_AddCommand ("inven", NULL);
                   1528:        Cmd_AddCommand ("kill", NULL);
                   1529:        Cmd_AddCommand ("use", NULL);
                   1530:        Cmd_AddCommand ("drop", NULL);
                   1531:        Cmd_AddCommand ("say", NULL);
                   1532:        Cmd_AddCommand ("say_team", NULL);
                   1533:        Cmd_AddCommand ("info", NULL);
                   1534:        Cmd_AddCommand ("prog", NULL);
                   1535:        Cmd_AddCommand ("give", NULL);
                   1536:        Cmd_AddCommand ("god", NULL);
                   1537:        Cmd_AddCommand ("notarget", NULL);
                   1538:        Cmd_AddCommand ("noclip", NULL);
                   1539:        Cmd_AddCommand ("invuse", NULL);
                   1540:        Cmd_AddCommand ("invprev", NULL);
                   1541:        Cmd_AddCommand ("invnext", NULL);
                   1542:        Cmd_AddCommand ("invdrop", NULL);
                   1543:        Cmd_AddCommand ("weapnext", NULL);
                   1544:        Cmd_AddCommand ("weapprev", NULL);
                   1545: }
1.1.1.2   root     1546: 
                   1547: 
                   1548: 
1.1       root     1549: /*
                   1550: ===============
                   1551: CL_WriteConfiguration
1.1.1.2   root     1552: 
1.1       root     1553: Writes key bindings and archived cvars to config.cfg
                   1554: ===============
                   1555: */
                   1556: void CL_WriteConfiguration (void)
                   1557: {
                   1558:        FILE    *f;
                   1559:        char    path[MAX_QPATH];
1.1.1.2   root     1560: 
1.1       root     1561:        if (cls.state == ca_uninitialized)
                   1562:                return;
1.1.1.2   root     1563: 
1.1       root     1564:        Com_sprintf (path, sizeof(path),"%s/config.cfg",FS_Gamedir());
                   1565:        f = fopen (path, "w");
                   1566:        if (!f)
                   1567:        {
                   1568:                Com_Printf ("Couldn't write config.cfg.\n");
                   1569:                return;
                   1570:        }
1.1.1.2   root     1571: 
1.1       root     1572:        fprintf (f, "// generated by quake, do not modify\n");
                   1573:        Key_WriteBindings (f);
                   1574:        fclose (f);
1.1.1.2   root     1575: 
1.1       root     1576:        Cvar_WriteVariables (path);
                   1577: }
                   1578: 
1.1.1.2   root     1579: 
1.1       root     1580: /*
                   1581: ==================
                   1582: CL_FixCvarCheats
                   1583: 
                   1584: ==================
                   1585: */
                   1586: 
                   1587: typedef struct
                   1588: {
                   1589:        char    *name;
                   1590:        char    *value;
                   1591:        cvar_t  *var;
                   1592: } cheatvar_t;
                   1593: 
                   1594: cheatvar_t     cheatvars[] = {
                   1595:        {"timescale", "1"},
                   1596:        {"timedemo", "0"},
                   1597:        {"r_drawworld", "1"},
                   1598:        {"cl_testlights", "0"},
                   1599:        {"r_fullbright", "0"},
                   1600:        {"r_drawflat", "0"},
                   1601:        {"paused", "0"},
                   1602:        {"fixedtime", "0"},
1.1.1.2   root     1603:        {"sw_draworder", "0"},
                   1604:        {"gl_lightmap", "0"},
                   1605:        {"gl_saturatelighting", "0"},
1.1       root     1606:        {NULL, NULL}
                   1607: };
                   1608: 
                   1609: int            numcheatvars;
                   1610: 
                   1611: void CL_FixCvarCheats (void)
                   1612: {
                   1613:        int                     i;
                   1614:        cheatvar_t      *var;
                   1615: 
                   1616:        if ( !strcmp(cl.configstrings[CS_MAXCLIENTS], "1") 
                   1617:                || !cl.configstrings[CS_MAXCLIENTS][0] )
                   1618:                return;         // single player can cheat
                   1619: 
                   1620:        // find all the cvars if we haven't done it yet
                   1621:        if (!numcheatvars)
                   1622:        {
                   1623:                while (cheatvars[numcheatvars].name)
                   1624:                {
                   1625:                        cheatvars[numcheatvars].var = Cvar_Get (cheatvars[numcheatvars].name,
                   1626:                                        cheatvars[numcheatvars].value, 0);
                   1627:                        numcheatvars++;
                   1628:                }
                   1629:        }
                   1630: 
                   1631:        // make sure they are all set to the proper values
                   1632:        for (i=0, var = cheatvars ; i<numcheatvars ; i++, var++)
                   1633:        {
                   1634:                if ( strcmp (var->var->string, var->value) )
                   1635:                {
                   1636:                        Cvar_Set (var->name, var->value);
                   1637:                }
                   1638:        }
                   1639: }
1.1.1.2   root     1640: 
1.1       root     1641: //============================================================================
                   1642: 
                   1643: /*
                   1644: ==================
                   1645: CL_SendCommand
                   1646: 
                   1647: ==================
                   1648: */
                   1649: void CL_SendCommand (void)
                   1650: {
                   1651:        // get new key events
                   1652:        Sys_SendKeyEvents ();
                   1653: 
                   1654:        // allow mice or other external controllers to add commands
                   1655:        IN_Commands ();
                   1656: 
                   1657:        // process console commands
                   1658:        Cbuf_Execute ();
                   1659: 
                   1660:        // fix any cheating cvars
                   1661:        CL_FixCvarCheats ();
                   1662: 
                   1663:        // send intentions now
                   1664:        CL_SendCmd ();
                   1665: 
                   1666:        // resend a connection request if necessary
                   1667:        CL_CheckForResend ();
                   1668: }
1.1.1.2   root     1669: 
                   1670: 
1.1       root     1671: /*
                   1672: ==================
                   1673: CL_Frame
1.1.1.2   root     1674: 
1.1       root     1675: ==================
                   1676: */
                   1677: void CL_Frame (int msec)
                   1678: {
                   1679:        static int      extratime;
                   1680:        static int  lasttimecalled;
1.1.1.2   root     1681: 
1.1       root     1682:        if (dedicated->value)
                   1683:                return;
1.1.1.2   root     1684: 
1.1       root     1685:        extratime += msec;
                   1686: 
                   1687:        if (!cl_timedemo->value)
                   1688:        {
                   1689:                if (cls.state == ca_connected && extratime < 100)
                   1690:                        return;                 // don't flood packets out while connecting
                   1691:                if (extratime < 1000/cl_maxfps->value)
                   1692:                        return;                 // framerate is too high
                   1693:        }
                   1694: 
                   1695:        // let the mouse activate or deactivate
                   1696:        IN_Frame ();
1.1.1.2   root     1697: 
1.1       root     1698:        // decide the simulation time
                   1699:        cls.frametime = extratime/1000.0;
                   1700:        cl.time += extratime;
                   1701:        cls.realtime = curtime;
1.1.1.2   root     1702: 
1.1       root     1703:        extratime = 0;
1.1.1.2   root     1704: #if 0
1.1       root     1705:        if (cls.frametime > (1.0 / cl_minfps->value))
                   1706:                cls.frametime = (1.0 / cl_minfps->value);
1.1.1.2   root     1707: #else
                   1708:        if (cls.frametime > (1.0 / 5))
                   1709:                cls.frametime = (1.0 / 5);
                   1710: #endif
                   1711: 
1.1       root     1712:        // if in the debugger last frame, don't timeout
                   1713:        if (msec > 5000)
                   1714:                cls.netchan.last_received = Sys_Milliseconds ();
                   1715: 
                   1716:        // fetch results from server
                   1717:        CL_ReadPackets ();
                   1718: 
                   1719:        // send a new command message to the server
                   1720:        CL_SendCommand ();
                   1721: 
                   1722:        // predict all unacknowledged movements
                   1723:        CL_PredictMovement ();
1.1.1.2   root     1724: 
1.1       root     1725:        // allow rendering DLL change
                   1726:        VID_CheckChanges ();
                   1727:        if (!cl.refresh_prepped && cls.state == ca_active)
                   1728:                CL_PrepRefresh ();
                   1729: 
                   1730:        // update the screen
                   1731:        if (host_speeds->value)
                   1732:                time_before_ref = Sys_Milliseconds ();
                   1733:        SCR_UpdateScreen ();
                   1734:        if (host_speeds->value)
                   1735:                time_after_ref = Sys_Milliseconds ();
1.1.1.2   root     1736: 
1.1       root     1737:        // update audio
                   1738:        S_Update (cl.refdef.vieworg, cl.v_forward, cl.v_right, cl.v_up);
                   1739:        
                   1740:        CDAudio_Update();
                   1741: 
                   1742:        // advance local effects for next frame
                   1743:        CL_RunDLights ();
                   1744:        CL_RunLightStyles ();
                   1745:        SCR_RunCinematic ();
                   1746:        SCR_RunConsole ();
                   1747: 
                   1748:        cls.framecount++;
                   1749: 
                   1750:        if ( log_stats->value )
                   1751:        {
                   1752:                if ( cls.state == ca_active )
                   1753:                {
                   1754:                        if ( !lasttimecalled )
                   1755:                        {
                   1756:                                lasttimecalled = Sys_Milliseconds();
                   1757:                                if ( log_stats_file )
                   1758:                                        fprintf( log_stats_file, "0\n" );
                   1759:                        }
                   1760:                        else
                   1761:                        {
                   1762:                                int now = Sys_Milliseconds();
                   1763: 
                   1764:                                if ( log_stats_file )
                   1765:                                        fprintf( log_stats_file, "%d\n", now - lasttimecalled );
                   1766:                                lasttimecalled = now;
                   1767:                        }
                   1768:                }
                   1769:        }
                   1770: }
1.1.1.2   root     1771: 
                   1772: 
1.1       root     1773: //============================================================================
1.1.1.2   root     1774: 
1.1       root     1775: /*
                   1776: ====================
                   1777: CL_Init
                   1778: ====================
                   1779: */
                   1780: void CL_Init (void)
                   1781: {
                   1782:        if (dedicated->value)
                   1783:                return;         // nothing running on the client
1.1.1.2   root     1784: 
1.1       root     1785:        // all archived variables will now be loaded
1.1.1.2   root     1786: 
1.1       root     1787:        Con_Init ();    
1.1.1.2   root     1788: #if defined __linux__ || defined __sgi
                   1789:        S_Init ();      
                   1790:        VID_Init ();
                   1791: #else
1.1       root     1792:        VID_Init ();
                   1793:        S_Init ();      // sound must be initialized after window is created
1.1.1.2   root     1794: #endif
1.1       root     1795:        
                   1796:        V_Init ();
                   1797:        
                   1798:        net_message.data = net_message_buffer;
                   1799:        net_message.maxsize = sizeof(net_message_buffer);
1.1.1.2   root     1800: 
1.1       root     1801:        M_Init ();      
                   1802:        
                   1803:        SCR_Init ();
                   1804:        cls.disable_screen = true;      // don't draw yet
1.1.1.2   root     1805: 
1.1       root     1806:        CDAudio_Init ();
                   1807:        CL_InitLocal ();
                   1808:        IN_Init ();
1.1.1.2   root     1809: 
1.1       root     1810: //     Cbuf_AddText ("exec autoexec.cfg\n");
                   1811:        FS_ExecAutoexec ();
                   1812:        Cbuf_Execute ();
1.1.1.2   root     1813: 
1.1       root     1814: }
1.1.1.2   root     1815: 
                   1816: 
1.1       root     1817: /*
                   1818: ===============
                   1819: CL_Shutdown
1.1.1.2   root     1820: 
1.1       root     1821: FIXME: this is a callback from Sys_Quit and Com_Error.  It would be better
                   1822: to run quit through here before the final handoff to the sys code.
                   1823: ===============
                   1824: */
                   1825: void CL_Shutdown(void)
                   1826: {
                   1827:        static qboolean isdown = false;
                   1828:        
                   1829:        if (isdown)
                   1830:        {
                   1831:                printf ("recursive shutdown\n");
                   1832:                return;
                   1833:        }
                   1834:        isdown = true;
1.1.1.2   root     1835: 
1.1       root     1836:        CL_WriteConfiguration (); 
1.1.1.2   root     1837: 
1.1       root     1838:        CDAudio_Shutdown ();
                   1839:        S_Shutdown();
                   1840:        IN_Shutdown ();
                   1841:        VID_Shutdown();
                   1842: }
                   1843: 
                   1844: 

unix.superglobalmegacorp.com

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